-
nginx javascript 모듈 - njsnginx 2022. 8. 29. 18:19반응형
nginx conf 파일에는 복잡한 로직을 넣을수 없습니다(예를 들어, 어떤 헤더가 존재하고 해당 값이 무엇보다 클 때 어떤 url로 redirect한다거나 특정 조건에서 응답 메시지에 헤더값을 추가한다거나).
복작한 로직을 구현할 수 있도록 nginx에서는 여러가지 모듈을 제공하고 있습니다. 이번 포스트에서는 javascript 모듈인 njs를 소개하려고 합니다.
https://nginx.org/en/docs/njs/
njs scripting language
njs scripting language njs is a subset of the JavaScript language that allows extending nginx functionality. njs is created in compliance with ECMAScript 5.1 (strict mode) with some ECMAScript 6 and later extensions. The compliance is still evolving. Use c
nginx.org
https://github.com/nginx/njs-examples/
GitHub - nginx/njs-examples: NGINX JavaScript examples
NGINX JavaScript examples. Contribute to nginx/njs-examples development by creating an account on GitHub.
github.com
참고로 비슷한 모듈로 lua module도 있습니다(뭔가 예제를 보면 njs보다 사용하기 편한것 같습니다).
https://github.com/openresty/lua-nginx-module
GitHub - openresty/lua-nginx-module: Embed the Power of Lua into NGINX HTTP servers
Embed the Power of Lua into NGINX HTTP servers. Contribute to openresty/lua-nginx-module development by creating an account on GitHub.
github.com
njs 모듈 설치 방법
1. dynamic modules 사용: 1.9.11 버전 이후부터 nginx-module-njs는 linux에서 dynamic module로 사용할 수 있습니다.
apt-get install nginx-plus-module-njs 설치후 nginx conf에서 load_module 명령으로 loading할 수 있습니다. load_module modules/ngx_http_js_module.so; load_module modules/ngx_stream_js_module.so;
2. 1.9.11 이전 버전에서는 nginx 빌드에서 --add-module 명령으로 njs module를 포함해서 빌드해야 사용할 수 있습니다. 저희 팀에서는 1.9.11 이전 버전 nginx라 이 방법을 사용했습니다.
njs 소스코드는 하기 페이지에서 zip으로 다운받을 수 있습니다.
http://hg.nginx.org/njs
hg.nginx.org
저는 하기와 같이 nginx에 njs module을 추가해서 빌드했습니다.
FROM centos:7 ARG NGINX_VER=1.14.2 ARG INST_PATH=/home1/apps RUN curl -SL http://nginx.org/download/nginx-${NGINX_VER}.tar.gz | tar -xzC ./ ARG NJS_MODULE_FILE_NAME=njs-43b31a943c08 ARG NJS_MODULE_FILE_EXTENSION=.tar.gz COPY ./${NJS_MODULE_FILE_NAME}${NJS_MODULE_FILE_EXTENSION} ./${NJS_MODULE_FILE_NAME}${NJS_MODULE_FILE_EXTENSION} RUN tar -xf ${NJS_MODULE_FILE_NAME}${NJS_MODULE_FILE_EXTENSION} && rm -f ${NJS_MODULE_FILE_NAME}${NJS_MODULE_FILE_EXTENSION} ARG NJS_ADD_MODULE_OPTION="--add-module=/${NJS_MODULE_FILE_NAME}/nginx" # install dependent lib RUN yum install -y gcc-c++ which make pcre-devel pcre openssl-devel openssl mod_ssl libcurl-devel # build and install nginx RUN mkdir -p ${INST_PATH}/nginx-${NGINX_VER} && cd nginx-${NGINX_VER} && ./configure --prefix=${INST_PATH}/nginx-${NGINX_VER} ${NJS_ADD_MODULE_OPTION} && make install && cd ${INST_PATH} && tar -czf nginx.tar.gz nginx-${NGINX_VER} RUN ln -sf ${INST_PATH}/nginx-${NGINX_VER} ${INST_PATH}/nginx # nginx conf COPY ./nginx.conf ${INST_PATH}/nginx/conf # js file copy COPY ./njs ${INST_PATH}/nginx/njs WORKDIR ${INST_PATH}/nginx ENV PATH="${INST_PATH}/nginx/sbin:${PATH}" CMD ["nginx", "-g", "daemon off;"] EXPOSE 80 EXPOSE 443
- centos 환경을 사용함.
- nginx와 njs module를 다운받아서 build 함.
- nginx conf 파일 복사
- njs 파일 복사(아래에서 설명)
- nginx 실행
njs 파일 추가 및 nginx conf 파일 설정
1. njs function이 존재하는 js파일을 생성해야 합니다. 저는 njs 폴더 밑에 njs.js 파일을 생성하였고 하기와 같이 test function을 추가했습니다.
function hello(r) { r.return(200, 'Hello world!\n') } function apiAddr(r) { const header = 'version' const headerValue = r.headersIn[header] if (headerValue === 'new') { r.log(`exist________${header}: ${headerValue}`) return 'http://127.0.0.1/new_api' } return 'http://127.0.0.1/old_api' } export default { hello, apiAddr }
function을 생성 후 마지막에 export 하고 nginx.conf에서 사용하면 됩니다.
2. nginx.conf에서는 하기와 같은 설정을 해주면 njs function을 사용할 수 있습니다.
- js_path: njs 파일이 존재하는 폴더 지정
- js_import: njs 파일명
- js_set: njs function을 변수로 지정 후 사용할 수 있음
예제로 하기와 같이 nginx.conf를 생성했습니다.
events { worker_connections 1024; } http { js_path "/home1/apps/nginx/njs"; js_import njs from 'njs.js'; js_set $apiAddr njs.apiAddr; server { listen 80; location /njs_test { js_content njs.hello; } location /njs_api { proxy_pass $apiAddr; } location /new_api { return 200 'This is new api!!!'; } location /old_api { return 200 'This is old api!!!'; } location / { return 200 'OK'; } } }
예제 테스트
1. http://localhost/njs_test 를 postman에서 실행하면 하기와 같이 "Hello world"를 볼수 있습니다.
2. http://localhost/njs_api 로 하고 header에 version 값으로 new를 주면 하기와 같이 new_api가 실행됨을 볼수 있습니다.
예제 github 소스코드: https://github.com/quanjichun/nginx-docker-njs
주의할 점
1. njs는 avascript 기능을 모두 지원하는것이 아닙니다. javascript의 부분집합이라고 생각하면 됩니다. 따라서 v8 engine이 아니라 자체구현한 engine을 사용합니다(v8보다 많이 가볍다고 합니다). https://nginx.org/en/docs/njs/compatibility.html 를 참고하면 되겠습니다.
2. njs는 garbage collector 가 존재하지 않습니다. 각 http 요청마다 javascript vm이 생성되고 요청이 끝나면 release 하는 형식으로 동작합니다. 때문에 요청 처리시간이 오래 걸리는 요청에는 njs를 사용하지 않고 메모리를 많이 사용하는 로직은 피해야 합니다. 애초에 njs는 nodejs와 같은 웹서버가 아니라 proxy 서버에서 진행해야 하는 간단한 로직을 처리한다고 생각하는것이 맞을것 같습니다.
저희 회사 다른 팀에서는 njs를 리얼 서비스에 적용한 사례도 있습니다. 요청마다 vm을 loading하면 메모리 이슈가 걱정이 되긴 한데 그래도 필요하다면 리얼 서비스에 적용해보고 판단하는것도 좋을 것 같습니다.
반응형'nginx' 카테고리의 다른 글
nginx 요청 처리 단계(Phases) 관련 (0) 2022.08.29 [Docker + nginx] 로 static 파일 서버 만들기 (Windows) (0) 2020.11.19