Node.js MaxListener 에러 수정

웹소켓 테스트 중 마주친 에러.

대략 코드상으로는 별 문제가 없는데 실행시 이러한 에러가 나왔다.

(node:5828) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit

해결방법은

를 참고하여 해결.

코드 중간에 다음과 같은 코드를 삽입한다.

require('events').EventEmitter.prototype._maxListeners = 100;

그런데 이 코드를 넣으면 이벤트 전반에 대한 리스너 갯수를 변경하는지라… 글로벌하게 변경해도 되나 모르겠네. 웹소켓 객체에다가만 적용하는 방법을 더 찾아봐야할 것 같다.

Lightsail 에서 NGINX에 SSL 적용하기 (2)

제대로 접속이 된다면 Lightsail 관리자페이지에서 HTTPS 접속을 위한 환경을 추가한다. ssl.83rpm.com 도메인을 추가한 다음, 443 포트를 연다.

이제 SSL 설정을 시작한다.

내가 수정해야될 사이트의 가상호스트 설정 파일을 연다. 내 경우에는, /opt/bitnami/apps/ssl.83rpm.com/conf/nginx-vhost.conf 파일.

기존의 파일 내용은 다음과 같다.

server {
        listen          80;
        root            /opt/bitnami/apps/ssl.83rpm.com/htdocs;
        server_name     ssl.83rpm.com;
        client_max_body_size    40M;
        include         "/opt/bitnami/apps/ssl.83rpm.com/conf/nginx-app.conf";
}

이 파일 내용을 다음과 같이 변경한다.

server {
        listen          80;
        root            /opt/bitnami/apps/ssl.83rpm.com/htdocs;
        server_name     ssl.83rpm.com;
        client_max_body_size    40M;
        include         "/opt/bitnami/apps/ssl.83rpm.com/conf/nginx-app.conf";
}

server {
        listen                  443 ssl;
        root                    /opt/bitnami/apps/ssl.83rpm.com/htdocs;
        server_name             ssl.83rpm.com;
        ssl_certificate         /opt/bitnami/nginx/ssl/server.crt;
        ssl_certificate_key     /opt/bitnami/nginx/ssl/server.key;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_timeout     5m;
        ssl_ciphers             HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        include                 "/opt/bitnami/apps/ssl.83rpm.com/conf/nginx-app.conf";
}

수정이 완료되었다면 lightsail 재시작 명령어로 모두 재시작한다.

sudo /opt/bitnami/ctlscript.sh restart

재시작하고 난 뒤 웹브라우저를 열고 https://ssl.83rpm.com 으로 접속이 잘 되는지 확인해본다.

구글 크롬과 인터넷 익스플로러의 경우 다음과 같이 표시된다.

내가 임의로 생성한 인증서이므로 안전하지 않기에 경고가 표시되지만 경고를 무시하면 어찌됐든 잘 표시된다.

만약, HTTP로 접속하더래도 무조건 HTTPS로 강제로 접속시키고 싶다면, nginx-vhost.conf 파일을 열고 다음과 같은 설정을 추가한다.

server {
        listen          80;
        root            /opt/bitnami/apps/ssl.83rpm.com/htdocs;
        server_name     ssl.83rpm.com;
        client_max_body_size    40M;
        include         "/opt/bitnami/apps/ssl.83rpm.com/conf/nginx-app.conf";
        rewrite ^ https://$server_name:443?request_uri? permanent;
}

server {
        listen                  443 ssl;
        root                    /opt/bitnami/apps/ssl.83rpm.com/htdocs;
        server_name             ssl.83rpm.com;
        ssl_certificate         /opt/bitnami/nginx/ssl/server.crt;
        ssl_certificate_key     /opt/bitnami/nginx/ssl/server.key;
        ssl_session_cache       shared:SSL:1m;
        ssl_session_timeout     5m;
        ssl_ciphers             HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        include                 "/opt/bitnami/apps/ssl.83rpm.com/conf/nginx-app.conf";
}

엔진엑스를 재실행하면 이제부터는 http로 접속하더라도 https 로 자동전환된다.

테스트하려면 http://ssl.83rpm.com 혹은 https://ssl.83rpm.com 으로 접속해보시길. (언제 닫을지는 모릅니다.)

참고자료

Lightsail 에서 NGINX에 SSL 적용하기 (1)

Lightsail을 사용하며 SSL을 적용하는 방법에 대한 포스팅이다. SSL을 써본적도 없고 앞으로도 내가 이런걸 쓸일이 있을지는 모르겠으나 한번 시도해본다. (사실은 푸우시로님의 요청으로)

나는 상용인증서를 구매할 생각이 없으므로 셀프로 생성해서 테스트해보기로 했다.

이제부터 쓸 내용은 AWS Lightsail NGINX 스택에서 설정한 것이며 운영체제는 우분투 리눅스, 웹서버는 nginx 이다. 굳이 lightsail에만 국한된 것은 아니고 어떤 리눅스라도 같은 과정을 거치면 HTTPS 설정이 가능하다. 상용인증서를 사용한다해도 인증서 공급업체의 인증서를 쓸뿐이지 다른 과정은 똑같다.

https://goo.gl/gBSf5b

을 참고하여 인증서를 생성한다.

아래부터의 내용은 위 URL에 있는 개인인증서 생성을 직접 실행해본 것이다.

bitnami@ip-172-26-10-176:~$ openssl version
OpenSSL 1.0.2l  25 May 2017
bitnami@ip-172-26-10-176:~$

명령으로 openssl이 설치되어 있는지 확인한다. 설치가 되어있지 않다면 apt-get install openssl로 openssl 패키지를 설치한다.

개인키를 생성한다.

bitnami@ip-172-26-10-176:~$ openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
....................................+++
............................+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
bitnami@ip-172-26-10-176:~$

인증요청서를 생성한다. 몇가지 입력을 요구하는데 자기 상황에 맞도록 알아서 입력한다. 챌린지패스워드와 옵셔널 컴패니 네임은 입력하지 말라고 해서 그냥 엔터쳐서 넘기면 된다.

bitnami@ip-172-26-10-176:~$ openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seadaemoon-gu
Organization Name (eg, company) [Internet Widgits Pty Ltd]:83RPM.com
Organizational Unit Name (eg, section) []:83RPM.com
Common Name (e.g. server FQDN or YOUR name) []:83rpm.com
Email Address []:YOUR_EMAIL@gmail.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
bitnami@ip-172-26-10-176:~$

개인키에서 패스워드 제거하기

bitnami@ip-172-26-10-176:~$ cp server.key server.key.origin
bitnami@ip-172-26-10-176:~$ openssl rsa -in server.key.origin -out server.key
Enter pass phrase for server.key.origin:
writing RSA key
bitnami@ip-172-26-10-176:~$

인증서 생성

bitnami@ip-172-26-10-176:~$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=KR/ST=Seoul/L=Seadaemoon-gu/O=83RPM.com/OU=83RPM.com/CN=83rpm.com/emailAddress=YOUR_EMAIL@gmail.com
Getting Private key
unable to write 'random state'
bitnami@ip-172-26-10-176:~$

여기까지 하고 나면, server.crt / server.csr / server.key / server.key.origin 이렇게 4개의 파일이 생긴다.

인증서 파일들을 넣을 폴더를 생성한다. 나는 /opt/bitnami/nginx/ssl 로 지정했다. 이걸로 할 필요는 없으니 자기 마음대로 결정한다. (예를 들면, 사이트마다 설정할 사람은 apps 디렉토리의 자기사이트 디렉토리 밑에 만드는게 더 나을 것이다.)

bitnami@ip-172-26-10-176:~$ sudo mkdir /opt/bitnami/nginx/ssl

생성된 3개의 파일을 인증서 관리용 디렉토리로 복사한다.

bitnami@ip-172-26-10-176:~$ sudo cp server.crt /opt/bitnami/nginx/ssl/
bitnami@ip-172-26-10-176:~$ sudo cp server.csr /opt/bitnami/nginx/ssl/
bitnami@ip-172-26-10-176:~$ sudo cp server.key /opt/bitnami/nginx/ssl/

SSL을 적용할 사이트에 설정을 시작한다.

난 SSL 테스트를 위한 것이므로 따로 SSL을 위한 사이트 설정을 하나 만들었다. 주소는 ssl.83rpm.com 으로 하기로 했다. 사이트 설정을 한다. vhost 등등….

일단 http://ssl.83rpm.com 으로 접속해본다. 만약 여기서 제대로 접속이 안된다면 nginx 가상호스트 설정이 제대로 안되었으니 제대로 나올 떄까지 수정해야된다.

 

글의 내용이 너무 길어져 두 포스팅으로 나눠서 써야겠다.

docker 시작시 에러

집에 갑자기 정전이 와서 서버가 꺼져버렸다.

서버가 다시 살아나고 도커로 사용하던 컨테이너들을 재시작하려고 하니 에러가 났다.

[root@localhost ~]# docker start plex
Error response from daemon: error creating overlay mount to /var/lib/docker/overlay2/40a78337fb7041d7de6ccd93467be6ec60f7baf325f062c97e24cc4d01a13d91/merged: invalid argument
Error: failed to start containers: plex
[root@localhost ~]#

이 문제를 해결하기 위해 구글 검색을 해보았으나 딱히 좋은 의견은 보질 못했다.

docker container list 명령으로 컨테이너를 찾아보았으나 보이지 않았다. docker ps 명령으로 찾아서 모든 컨테이너를 삭제한다.

[root@localhost docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7d613c08b1f2 linuxserver/tautulli "/init" 7 days ago Exited (255) 3 hours ago tautulli
fdcb9b590e94 linuxserver/transmission "/init" 8 days ago Exited (255) 3 hours ago transmission
246a6d8a721b plexinc/pms-docker "/init" 10 days ago Exited (255) 3 hours ago plex
3040fb42bd81 oznu/homebridge "/init" 12 days ago Exited (255) 3 hours ago homebridge
[root@localhost docker]# docker container rm 7d613c08b1f2
7d613c08b1f2
[root@localhost docker]# docker container rm fdcb9b590e94
fdcb9b590e94
[root@localhost docker]# docker container rm 246a6d8a721b
246a6d8a721b
[root@localhost docker]# docker container rm 3040fb42bd81
3040fb42bd81

컨테이너를 모두 삭제하고 다시 컨테이너 실행스크립트를 이용해 새로운 컨테이너를 만들어서 실행시키니 해결되었다.

 

정전 같은 이유로 불완전하게 종료되었을 경우, 도커의 재실행에 문제가 생긴다. 이를 해결하는 방법 또한 시원하게 나온게 없었다. 컨테이너가 제대로 실행되지 않는다면 다 삭제하고 다시 실행하는게 차라리 빠르다.

귀찮은 실행스크립트를 다시 작성하지 않도록 잘 보관해야 한다.

Docker 설치 사용 후기

최근에 홈오토메이션을 잠깐 만져보다가 Docker를 접하게 되었다.

그동안 도커도커 얘기만 들어보고 개념만 들어봤지 이게 무엇인지 제대로 몰랐는데 이제는 좀 써봐야겠다 싶어서 도커에 대한 책도 한권 구매해서 정독하고 마이크로서버도 도커 기반으로 변경. 어차피 몇가지 서비스가 운영되지 않았기 때문에 도커로 옮기는건 별로 어렵지 않았으나 이왕이면 깨끗한 상태에서 돌리는게 기분 좋으니 CentOS 7 로 재설치하고 도커 기반으로 이전했다.

plex, transmission, nginx, homebridge 정도만 도커로 돌려보니 이제 이게 뭔지 좀 알 것 같다.

도커를 사용해본 후기.

  1. 전가상화와 비교할 수 없을 정도로 강력함.
    ESXI를 이용해 가상화로 서버를 돌려봤는데… 이건 운영체제 선택의 자유로움이 있고 정말 완벽한 격리환경이 되는 반면에, 가상화를 한다해도 자원을 너무나 많이 소모했다. 특히 게스트 운영체제 구동에 자원이 많이 드니… 이렇게까지 해야하나 싶었는데, 도커는 호스트 운영체제의 성능을 거의 그대로 쓸 수 있고, 자원도 많이 들지 않는다.아마 리눅스 서버를 가상화해서 쓴다면 ESXI보다 Docker가 정답인듯하다.
  2. 라이브러리 설치에서 해방
    yum이 나오면서 의존성에 대한 패키지 설치는 거의 자동화가 이루어졌긴하지만 서버에 프로그램을 설치하다보면 수많은 패키지들이 같이 설치가 된다. 시스템이 얼마나 더럽혀지는지도 알 수가 없고, 내가 쓰던 프로그램을 언인스톨한다고 해서 이 라이브러리와 패키지들이 같이 삭제되는건 아니기 때문에 과도한 관련 패키지와 라이브러리 설치는 별로 마음에 들지 않았었다.그런데, 도커로 오니 이러한게 한방에 해결. 더이상 운영체제가 각종 라이브러리 파일로 더럽혀질 일은 없을듯하다.
  3. 컨테이너 실행 옵션이 바뀌면 컨테이너를 통째로 지우고 다시 만들어야함.
    도커 사용시 약간 귀찮은 점. 어쩌면 방법이 있는데 내가 도커를 아직 잘 몰라서 못 찾은 것일 수도.
  4. 이미지에서 지원하지 않는 기능과 옵션에 대해서 내가 처리 불가능.
    사용하고자하는 이미지마다 정해진 옵션이 있고 이 옵션들에 대해서만 사용 가능하다.
    물론 그 부분을 내가 수정하여 이미지를 만들면서 사용하면 해결가능하다.
  5. 하지만 그럼에도 장점이 크다.
    호스트 운영체제의 시스템을 전혀 건드리지 않으면서 프로그램을 실행할 수 있다는건 정말 큰 장점.
  6. 실서비스에서 사용 가능한가…?
    사용해본 경험으로는 실서비스에 충분히 사용가능할듯하다.
    특히, 같은 이미지만 사용한다면 어디서나 같은 컨테이너를 돌릴 수 있다는게 최고의 장점인 것 같다.
    경험상 리눅스서버 사용시에는 운영체제 버전이 다르면 라이브러리 충돌 때문에 애먹는 경우가 많은데 도커가 그 해답이 될 수 있을 것 같다.

도커도커 왜들 그리 도커를 찾았나 얘기해서 사용해봤더니 실제로 아주 훌륭했다. 좀더 사용해보면 장단점이 더 많이 보이겠지.

Windows에서 Jenkins 설치하기

CentOS에서 Jenkins를 설치하는 글을 썼었는데 이제는 윈도우에서 설치해보기로 했다.

Jenkins 홈페이지에 보면 젠킨스를 여러가지 버전으로 제공하고 있다. 각 운영체제에 맞도록 인스톨러를 제공하고 있다. 톰캣 따로 설치해서 설정하는게 귀찮아서 그냥 Windows Stable Installer 버전으로 다운로드 받고 설치한다.

http://127.0.0.1:8080 에 접속해보면 젠킨스 화면이 나온다.

빨강색 글씨에 있는 경로를 찾아사 initialAdminPassword 의 암호를 입력해준다. Setup Wizard가 실행되면 따라서 진행한다. 플러그인을 수동으로 선택하여 설치할지 추천하는 플러그인을 설치할지 나오는데 난 그냥 귀찮아서 제안하는대로 설치했다.

플러그인을 잠시 설치하고 나면 관리자 계정을 생성한다. 관리자 계정까지 생성하고 나면 http://localhost:8080/ 로 들어가면 젠킨스가 실행된다.

Visual Studio에서 jemalloc 설치하고 사용법 (1)

이 글은 jemalloc 을 설치하다가 애먹은 경험으로 쓰는 것. 혹시 나처럼 Visual Studio에서 jemalloc을 쓰려고 고생하는 사람들에게 도움이 되길 바란다. 그리고 퍼갈 때에는 출처도 밝혀주시기를…

tcmalloc 이 VIsual Studio 2015 에서 작동이 제대로 안된다는 것을 알고 난 이후 다른 대안을 찾아보았다. 비슷한 기능을 하는 것으로 jemalloc과 nedmalloc가 있었는데 nedmalloc은 github에서 보니 개발이 멈춘지가 한참전이었다. 몇년전부터 개발이 중지된 것을 쓰기는 싫기에 jemalloc을 다운받았다.

jemalloc 에 대한 성능이나 기술적인 이야기는 마지막 남은 공짜 점심. Facebook의 메모리 할당자 jemalloc라는 글에 잘 설명되어 있다. 한번 읽어보는 것도 괜찮겠다.

참고로 jemalloc 이 현재 쓰이는 곳은 github의 IntendedUse 항목에서 찾아볼 수 있다.

에서 쓰이고 있다고 한다. 개발자라면 대부분 알만한 유명한 프로젝트들.

Visual Studio에서 jemalloc 설치하고 사용법 (3)

jemalloc 라이브러리가 정상 작동하므로 솔루션에 포함되어 있는 test_threads 프로젝트를 빌드해본다.

별 설정 없이도 잘 빌드되고 실행된다.

….만, 이게 도대체 뭔 내용인지는 나도 잘 모르겠다. test_threads.cpp 파일에는 테스트용 코드가 잔뜩 있다. 다 읽어보기도 힘들어서 읽어보다가 관둿다. 대략 je_malloc, je_free 등의 함수를 이용하는 예제코드인 것 같다.

github에는 간단한 예제코드가 있다. ( https://github.com/jemalloc/jemalloc/wiki/Getting-Started )

….는 별로 도움이 되지 않았다.

그냥 쉽게 얘기하면 new/malloc 을 할 때 je_malloc 을 하면 되고 delete/free 를 할 때 je_free 를 하라면 되는 말.

그래서 new와 delete를 오버라이딩하는 클래스를 만든다.

new 를 사용하는 곳에서 이 오버라이딩 클래스를 상속 받게 해주면 끝.

그리고 헤더에서 #include <jemalloc/jemalloc.h> 를 넣어주고 추가 포함 디렉터리에는 jemalloc의 include 디렉토리를 지정해주고 빌드하면 된다.

이렇게하면 빌드가 성공하고 실행파일에 있는 위치에 jemalloc 빌드 후 생성된 .dll 파일을 같이 넣어주면 된다.

….인줄 알았는데 빌드가 안된다.

코드를 보니 jemalloc.h 파일에서

#include <string.h> 부분이 문제가 되었다. 이 문제에 대해 찾아보니…

https://stackoverflow.com/questions/15512790/error-about-finding-strings-h-in-htmlcxx

아마 유닉스쪽에서 쓰는 헤더파일일 거라고 한다.

해당 부분을

#ifdef _WIN32
#include <string.h> 
#else
#include <strings.h>
#endif

로 교체하면 잘 작동한다.

프로젝트의 구성속성을 보면 Debug, Debug-static 식으로 나뉘어 있는데, 전자는 .dll 파일을 쓰는 동적 링크, 후자는 .lib 파일을 쓰는 정적 링크이다. 각자 원하는 것으로 사용.

Visual Studio에서 jemalloc 설치하고 사용법 (2)

이 글은 jemalloc 을 설치하다가 애먹은 경험으로 쓰는 것. 혹시 나처럼 Visual Studio에서 jemalloc을 쓰려고 고생하는 사람들에게 도움이 되길 바란다. 그리고 퍼갈 때에는 출처도 밝혀주시기를…

일단 https://github.com/jemalloc/jemalloc 에서 소스코드를 Clone 한다. (내 경우에는 D:\Library\jemalloc 으로 다운로드했다.)

master 브랜치를 다운로드하고 안에 들어가서 살펴보면 msvc 라는 디렉토리가 있고 그 안에 jemalloc_vc2015.sln 파일이 있다. Visual Studio 2015용 솔루션이 있으니 얼마나 감사한가.

솔루션을 열어보면 이미 jemalloc 프로젝트와 test_threads 프로젝트가 추가되어있다.

jemalloc 프로젝트를 빌드해보면…

C1083 포함 파일을 열 수 없습니다. 'jemalloc/internal/jemalloc_preamble.h': No such file or directory jemalloc d:\library\jemalloc\src\witness.c 2
오류와 함께 빌드가 되지 않는다. 실제로 저 경로에 가서 살펴보면 jemalloc_preamble.h 파일이 없다.

솔루션 파일에 추가되어 있는 ReadMe.txt 파일을 열어보면 다음과 같은 내용이 있다.
How to build jemalloc for Windows
=================================

1. Install Cygwin with at least the following packages:
* autoconf
* autogen
* gawk
* grep
* sed

2. Install Visual Studio 2015 with Visual C++

3. Add Cygwin\bin to the PATH environment variable

4. Open "VS2015 x86 Native Tools Command Prompt"
(note: x86/x64 doesn't matter at this point)

5. Generate header files:
sh -c "CC=cl ./autogen.sh"

6. Now the project can be opened and built in Visual Studio:
msvc\jemalloc_vc2015.sln

메뉴얼이 있으니 따라가야지.

Cygwin을 구글에서 검색해서 설치한다. Cygwin 설치법은 검색해서 찾자.

하나 참고해둘 것은 Cygwin은 설치프로그램을 실행해서 구성파일을 인터넷에서 다운로드하며 설치한다. 근데 이 과정이 무지막지하게 느리다. 기가인터넷이고 지랄이고 이런거 소용 없더라. 미러를 선택할 때 ftp.kaist.ac.kr을 선택했지만 그래도 느리다. 한참 설치하더니 몇가지 패키지가 설치 안되었다고 나온다. 설치프로그램을 다시 실행시켜서 미러를 ftp.jaist.ac.jp 로 바꾸고 다시 설치. 이 과정을 몇번 반복해서야 겨우 설치 완료했다.

Cygwin을 디폴트로 설치하고나서 설치프로그램의 검색창을 이용해 위 메뉴얼에 있는 autoconf, autogen, gawk, grep, sed를 설치해줘야 한다. 잊지말것.

아마 Cygwin을 처음 보거나 잘 쓰지 않는 사람이라면 이 과정에서 굉장히 스트레스 받을 것이다. 나도 Cygwin 설치에만 하루 넘게 걸렸다. 젠장…

이걸 설치하고 나서는 메뉴얼대로 제어판을 열고 ‘시스템’의 ‘고급 시스템 설정’의 ‘환경 변수’에 가서 ‘변수’ 중 Path 항목의 값에 Cygwin의 bin 경로를 추가해준다. 내 경우에는 C:\cygwin64\bin 을 추가해줬다.

이제 시작메뉴에서 ‘VS2015 x64 네이티브 도구 명령 프롬프트’를 실행한다.

경로를 jemalloc이 설치된 폴더로 이동한다. 내 경우에는 D:\Library\jemalloc 으로.

메뉴얼에 있는대로 sh -c “CC=cl ./autogen.sh” 를 입력한다.

각종 환경설정 사항을 체크하고 컴파일 과정이 지나간다. (다중프로세서 컴파일은 하지 않는듯하다. 적당히 웹서핑하며 몇분 기다리면 된다.)

이 화면이 나오면 컴파일이 끝난 것이다.

아까 jemalloc_preamble.h 파일이 없던 경로에 가보면 jemalloc_preamble.h 파일이 생성되어 있다.

이제 다시 Visual Studio 2015를 켜서 솔루션을 열고 jemalloc 프로젝트를 빌드해본다.

당연히 잘된다. ㅎㅎㅎ

결론 : Cygwin을 설치하는게 제일 애먹었다. 이것만 설치하고 나머지는 메뉴얼대로 설정하면 된다.