본문 바로가기
AWS

AWS Parse Server를 설치하고 PM2 사용하기

by RyanGomdoriPooh 2016. 5. 6.

저번 시간까지 MongoDB의 환경을 구축하고 추가사항이지만 MongoDB의 데이터들을 보안할 수 있는 SSL에 대해서 보았습니다.


이번에는 AWS 에 Parse Server를 설치하고, Parse Server Service를 중단되지않고 항상 작동하게끔 만들어주는 PM2에 대해서 설명을 해보겠습니다.


parse-server는 오픈소스를 페이스북에서 올려주셨기 때문에 설치하면되고,


PM2에 대해서는 생소하실 것 같아서 일단 설명을 하고 시작하겠습니다. 서비스를 하시려면 꼭 필요한 프로그램 중 하나입니다.


PM2는 forever라는 툴과 마찬가지로 서비스가 순간적인 트래픽이나 에러핸들링을 안해서 생기는 프로그램이 다운되는 경우가 많습니다.

특히 node.js 기반의 프로그램은 시스템을 엄청 정교하게 만들었다고해도 다운이 발생합니다.


그래서 node.js를 서버 사이드 언어로 사용하는 사람들은 해결책을 제시합니다.


정교하게 만들되, 죽으면 빠르게 다시 시작하는 형식으로 프로그램의 구동방식을 하면 그나마 서비스를 온전하게 만들 수 있다.


이 아이디어에서 만들어져서 나온 툴이 바로 PM2와 forever 라는 프로그램입니다.

하지만 

이 프로그램은 서비스를 하는 프로세스들을 관리, 죽으면 restart, Auto-Scaling, Load-Balancing 도 해줍니다. 

물론 네트워크 관점이 아닌 process 관점에서 해줍니다.


이제 parse-server랑 pm2 구축을 해보겠습니다. (Ubuntu 14.04 LTS)


1-1) 다운로드를 받기 전에 git과 bc를 다운로드로 최신화 시킵니다.

$ sudo apt-get -y install git bc


1-2) 처음으로는 일단 parse-server 와 pm2를 설치해 줍니다. 설치를 하는 것 자체는 어렵지 않습니다.

$ sudo npm install -g parse-server pm2

동시에 설치해 주셔도 되고 따로 설치해 주셔도 됩니다.

여기서 중요한 건 CLI환경에서 어느 경로든 사용할 수 있게 -g 옵션을 사용해서 Global로 설치를 해주셔야합니다.



2) 그리고 parse-server를 다룰 전용 사용자 아이디를 만들어 줍니다.

$ sudo useradd --create-home --system parse

그리고 parse 아이디가 만들어졌으니 패스워드를 수정해줍니다.

$ sudo passwd parse

그리고 home directory로 이동합니다.

parse $ sudo cd ~



3) parse-server에서 동시에 Node.js기반의 cloud code를 이용해서 다른 기능들을 추가하기 위해서 환경을 만들어 주겠습니다.

일단 cloud code를 담을 cloud 디렉토리를 만듦니다.

parse $ mkdir -p ~/cloud

그리고 Cloud를 구현할 js파일을 만듦니다.

parse $ nano ~/cloud/main.js

그리고 간단하게 다음과정에서 테스트를 할 수 있게 테스팅 소스를 넣어줍니다.

// 경로 : /home/parse/cloud/main.js

Parse.Cloud.define('hello', function(req, res) {

  res.success('Hi');

});

그리고 저장해줍니다.

기존의 parse에 cloud 소스가 있으신 분은 해당하는 소스를 직접 복사해서 붙여넣어줍니다.



4) PM2을 사용해서 parse-server의 js를 실행해서 사용해보겠습니다.

물론 직접 js파일을 찾아 들어가는 것도 괜찮지만 PM2에게 여러가지 옵션을 주어서 사용할 수 있게 하나의 json파일을 만들어서 관리하는 것이 편하고 좋습니다.

json 파일을 가지고 서버를 실행하는 방법에 대해서 설명하겠습니다.



parse-server를 실행시키고 PM2의 옵션을 달기위한 json 파일을 만들기 앞서서

https://dashboard.parse.com/apps 경로의 위 화면에 들어가서 Application ID 와 밑에 Master key 그리고

DB Migration에서 parameter로 넣었던 mongodb://[해당db접근ID]:[패스워드]@[해당서버의 domain]:27017/[가져온 DB명][?ssl=true] 을 준비합니다.


그리고 parse $ nano /home/parse/ecosystem.json 에 json파일을 만듦니다. 여기서 경로는 그냥 parse를 관리할 사용자로 parse계정의 경로라 보시면 됩니다. 어디에 두셔도 상관은 없습니다. 다만 전담 계정을 만들어서 폴더에 넣어두면 관리에 이점이 있습니다.


다음 내용을 완성해서 올리도록 합니다.


파일명-경로 : /home/parse/ecosystem.json

{

  "apps" : [{

    "name"        : "parse-wrapper",

    "script"      : "/usr/bin/parse-server",

    "watch"       : true,

    "merge_logs"  : true,

    "cwd"         : "/home/parse",

    "env": {

      "PARSE_SERVER_CLOUD_CODE_MAIN": "/home/parse/cloud/main.js",

      "PARSE_SERVER_DATABASE_URI": "mongodb://[해당db접근ID]:[패스워드]@[해당서버의 domain]:27017/[가져온 DB명][?ssl=true]",

      "PARSE_SERVER_APPLICATION_ID": "[Application ID]",

      "PARSE_SERVER_MASTER_KEY": "[Master Key]",

"PORT" : "[원하는 port#]"

    },

    "exec_mode": "cluster",

    "instances": 0

  }]

}


을 형식에 맞게 고쳐서 붙여 넣어주시면 됩니다. Bold 체를 주목해주세요.

위에 3개의 PARSE_SERVER key는 아신다고 가정하고 밑에 두개는 서비스를 시작하고 나면 performance에 대한 process관리가 필요하게 됩니다.

그래서 cluster기능을 사용하는데 process를 Auto-scaring 해주고 또한 Load-Balancing을 해줍니다. 그리고 instance를 0으로 두는 이유는 0으로 두면 자동적으로 MAX로 프로세스를 만들어서 서비스를 가능하게 합니다.


더많은 PAESE_SERVER 옵션을 셋팅하시고 싶다면 다음 옵션이 있습니다.


더 많은 참고~

https://www.npmjs.com/package/parse-server


그리고 이제 만들어진 ecosystem.json 파일을 가지고 PM2로 시작을 해보도록 하겠습니다.



5) parse $ pm2 start ecosystem.json -i 0 --name "원하는 app name"   // instance 옵션을 0, cpu의 갯수에 따라 자동으로 맞추어서 실행하는 옵션(로드밸런싱, cluster 기능)


다음과 같이 나오면 실행 시키시는데에 성공하신 겁니다.

그리고 pm2의 현재 process list를 저장해서 남겨둡니다. 나중에 참고가 될 수 있습니다.

parse $ pm2 save


이제 parse 계정모드를 나옵니다.

parse $ exit


그리고 현재 parse server 용으로 위에서 만들었던 parse 계정을 사용해서 Server를 자동 시작 할 수 있게끔 스크립트 시작을 명시해 줍니다.

$ sudo pm2 startup [실행 플레폼] -u [실행 유저 계정] --hp [실행파일의 디렉토리 여기선 ecosystem.json이 있는 디렉토리] ...[healthcheck app.js의 실행 경로를 넣어도 된다]

ex)

$ sudo pm2 startup ubuntu -u parse --hp /home/parse/


* 추가적으로 pm2의 명령어에 대해서 몇가지 설명을 드리겠습니다.

- parse $ pm2 start [실행시킬 서비스 파일명(app name)] [옵션추가는 자유]    // 서비스를 실행시킵니다.

- parse $ pm2 stop [id] // pm2로 시작한 서비스 일시정지 개념. 혹시 자동 재시작 옵션으로 서비스를 시작하면 다시 시작됩니다.

- parse $ pm2 list    // pm2로 시작한 서비스들의 목록을 보여줍니다.

- parse $ pm2 monit    // 실행 시킨 서비스의 CPU 점유율과 memory 사용률을 볼 수 있습니다.

- parse $ pm2 delete [id]    // 해당하는 실행 서비스를 stop처럼 일시정지 시키는 것이 아니고 아예 없애 버립니다.

- parse $ pm2 show [id]    // 해당하는 실행 서비스의 자세한 정보을 봅니다.

- parse $ pm2 reload [id/all]    // 해당 서비스를 종료하지 않고 리로드 합니다. 클러스터 모드일때 다운타임 없이 서버를 재가동 가능.

- parse $ pm2 scale [app name] [늘릴 프로세스 갯수 절대값]    // 절대값으로 3이면 3개로 만들고 여기서 6하면 3개를 늘려 6개를 만듦

- parse $ pm2 kill    // pm2의 서비스들을 종료하고, pm2로 종료하는 명령어

- parse $ pm2 logs ['all'|'PM2'|app_name|app_id] [--err|--out] [--lines ] [--raw] [--timestamp [format]]    // 서비스의 로그를 보는 명령어

- parse $ pm2 flush    // 로그파일을 지우는 것.

- parse $ pm2-dev run [app-name]    // 개발자 모드, 로그 실시간 제공, 파일 변경시 감지 자동 재시작.

일단은 이정도만 하고 나중에 pm2에 대한 부분을 하나의 주제로 다루겠습니다.




6) 이제 들어온 요청에 대해서 parse-server에게 reverse proxy를 제공하는 Nginx web server를  설치하겠습니다.

nginx는 정적인 data를 취급하고 들어온 요청에 대해서 방향성을 제시해 주는 역할인 Web Server라합니다. WAS랑은 다른 개념입니다.

Parse server에 SSL을 domain name 인증 받았기 때문에 설정을 해서 SSL을 사용할 수 있게 해줍니다.


일단 설치를 해보겠습니다.

$ sudo apt-get update

$ sudo apt-get install -y nginx


설치와 동시에 서버 실행과 같이 nginx는 실행되어집니다. 확인은 크롬이나 익스플로러에 server의 도메인이나 IP를 쳐보시면 알게 됩니다.


그리고 기본 환경 셋팅의 부분을 고쳐줍니다.

sudo nano /etc/nginx/sites-enabled/default


파일명-경로 : /etc/nginx/sites-enabled/default

# HTTP - redirect all requests to HTTPS

server {

    listen 80;

    listen [::]:80 default_server ipv6only=on;

    return 301 https://$host$request_uri;

}


# HTTPS - serve HTML from /usr/share/nginx/html, proxy requests to /parse/

# through to Parse Server

server {

        listen 443;

        server_name your_domain_name;


        root /usr/share/nginx/html;

        index index.html index.htm;


        ssl on;

        # Use certificate and key provided by Let's Encrypt:

        ssl_certificate /etc/letsencrypt/live/your_domain_name/fullchain.pem;

        ssl_certificate_key /etc/letsencrypt/live/your_domain_name/privkey.pem;

        ssl_session_timeout 5m;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

        ssl_prefer_server_ciphers on;

        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';


        # Pass requests for /parse/ to Parse Server instance at localhost:1337

        location /parse/ {

                proxy_set_header X-Real-IP $remote_addr;

                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                proxy_set_header X-NginX-Proxy true;

                proxy_pass http://localhost:1337/;

                proxy_ssl_session_reuse off;

                proxy_set_header Host $http_host;

                proxy_redirect off;

        }


        location / {

                try_files $uri $uri/ =404;

        }

}


Bold처리된 부분인 your_domain_name에 SSL 인증을 받았던 domain name을 넣어줍니다.

그리고 저장을 해주시고 다시 nginx를 구동해 주시면 nginx 셋팅이 마무리되게 됩니다.

$ sudo service nginx restart

* 추가로 nginx의 Process 관리 방법은 다음과 같습니다.

$ sudo service nginx stop

$ sudo service nginx start

$ sudo service nginx restart

직관적으로 위 명령어를 알아들으실 거라고 믿습니다.


그리고 서버가 시작시 자동으로 nginx가 재시작하게끔 확실하게 하고 싶다면

$ sudo update-rc.d nginx defaults

라고 명령어를 사용하시면 됩니다.


7) 모든 AWS parse-server 셋팅이 완료되었습니다. 이제 셋팅이 잘 되었는지 테스팅을 해봐야겠죠?

우선적으로 다음 셋팅이 되어있는지 부터 확인하셔야합니다.

- TLS/SSL certificate를 받아서 인증이 되어있는 지.

- certificate를 가지고 MongoDB를 보안하고 있는지.

- parse-server를 port 1337로 돌려서 서비스를 제공하고 있는지, key 셋팅이 잘되어있는지.

- pm2로 구동되서 서비스가 되어지고 있는지.

- nginx을 SSL로 가동하여 사용하고 있는지. https://your_domain_name/parse 다음으로 접속이 안되어야합니다.


다음 조건이 충족하는지 보고 다음 과정을 시작합니다.


Data를 요청해보기 위해서 curl 명령어의 옵션에 대해서 알아보고 시작하겠습니다.



POST형식으로 Data를 DB에 넣어 보겠습니다.


$ curl -X POST \

  -H "X-Parse-Application-Id: your_application_id" \

  -H "Content-Type: application/json" \

  -d '{"score":1337,"playerName":"Sammy","cheatMode":false}' \

  http://your_domain_name:1337/parse/classes/GameScore


Bold 처리된 부분을 수정해주고 명령어를 실행해줍니다.

밑에 https://your_domain_name 과 같은 경우는 SSL을 사용하는 경우는 https, SSL을 사용하지 않는 경우는 http로 수정해서 명령어를 사용합니다.


결과는 MongoDB에 GameScore라는 Collection이 하나 생기게 되고 그안에 내용은 명령어에 전달한 -d옵션의 json_data들이 넘겨져 저장되게 됩니다.


그리고 돌아오는 response 는


{"objectId":"YpxFdzox3u","createdAt":"2016-02-18T18:03:43.188Z"}


과 같은 응답이 돌아옵니다.



-----------------------------------------



이번에는 바로 위에서 POST 형식으로 넣은 data를 GET형식으로 불러오는 명령어를 사용해보겠습니다.


$ curl -H "X-Parse-Application-Id: your_application_id" http://your_domain_name:1337/parse/classes/GameScore


명령어를 통해서 MongoDB에 있던 해당하는 Collection GameScore 안에 들어있는 모든 document를 json형식으로 읽기만 합니다. 변경이나 추가는 하지 않습니다.


response는 다음과 같습니다.


{"results":[{"objectId":"BNGLzgF6KB","score":1337,"playerName":"Sammy","cheatMode":false,"updatedAt":"2016-02-17T20:53:59.947Z","createdAt":"2016-02-17T20:53:59.947Z"},{"objectId":"0l1yE3ivB6","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T03:57:00.932Z","createdAt":"2016-02-18T03:57:00.932Z"},{"objectId":"aKgvFqDkXh","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T04:44:01.275Z","createdAt":"2016-02-18T04:44:01.275Z"},{"objectId":"zCKTgKzCRH","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T16:56:51.245Z","createdAt":"2016-02-18T16:56:51.245Z"},{"objectId":"YpxFdzox3u","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T18:03:43.188Z","createdAt":"2016-02-18T18:03:43.188Z"}]}



-----------------------------------------



POST, GET 방식을 사용해서 데이터를 넣고 읽고 업데이트하고 지우는 작업을 정적인 CRUD 작업인가에 반해


이번에는 더 중요한 Cloud Code를 이용해서 그 결과물을 받아오는 것을 해보겠습니다.


위에 결과와는 다르게 마치 C와 같은 언어에서처럼 method를 만들어 parameter를 넣어서 내부 로직에 의해서 데이터가 가공되어서 return 되는 것과 같은 로직이 지금 하려는 것입니다.


home/parse/cloud/main.js 안에 있는 cloud code의 hello method를 읽어서 처리를 부탁하는 형식입니다.


curl -X POST \

  -H "X-Parse-Application-Id: your_application_id" \

  -H "Content-Type: application/json" \

  -d '{}' \

  http://your_domain_name:1337/parse/functions/hello


hello method가 바로 /cloud/main.js 파일 안에 선언된 function의 이름입니다.

해당 hello method 안에 있는 소스인 response함수의 내용이 보내지게 됩니다.


이 code에서 내용이 res.success('Hi');로 결과는 response하라는 것이 나옵니다.


결과는 다음과 같이 도착하게 됩니다.




여기까지 POST 이용해 data를 넣어보는 방법, GET 이용해 data를 가져오는 방법, 동적으로 data를 가공해서 전달받는 방법인 Cloud Code를 다 살펴 보았습니다.



8) 이제 Parse DB를 AWS로 migration하는 것부터 시작해서 이번 글의 AWS parse server 구동까지 마치셨고 마지막으로 mobile frontend에서 가리켜서 처리를 요청하는 방향을 바꾸어서 AWS Parse를 향하도록 수정만 하시면 끝이나게 됩니다.


그 과정은 간단하게 표현하자면

- 다음 사이트에 들어가서 Parse Server의 SDK를 Migration method가 포함된 최신 SDK로 교체, 추가해줍니다.

https://parse.com/docs/downloads


안드로이드의 경우)에는 https://github.com/ParsePlatform/Parse-SDK-Android 에 들어가서




이 부분을 소스에 추가해줍니다.


그리고


- 다음에 사이트에 들어가서 mobile에 사용하는 운영체제(Android, iOS 등등) 에 따라 Parse Server를 가리키는 방향(URL)을 코드에서 바꾸어줍니다.

https://github.com/ParsePlatform/parse-server/wiki/Parse-Server-Guide#using-parse-sdks-with-parse-server

사이트에 접속하셔서

안드로이드의 경우에는 이 부분입니다.






참고 :

https://www.digitalocean.com/community/tutorials/how-to-migrate-a-parse-app-to-parse-server-on-ubuntu-14-04


덤 :



댓글0