본문 바로가기

Study

[NGINX HTTP SERVER] 2장 기본 엔진엑스 구성

반응형

구성 파일 구문

지시어

  • 기본적으로 엔진엑스는 하나의 기본 구성 파일을 사용하며, 기본 경로는 /usr/local/nginx/conf/nginx.conf이다.
  • 엔진엑스 구성 파일은 지시어의 목록으로 이뤄져 있고, 지시어에 정의한 값으로 애플리케이션의 전체 동작을 정의한다.
    • user 지시어: 문자열 두 개를 받는다. 첫째는 엔진엑스가 작업자 프로세스를 실행하기 위한 사용자 계정, 둘째는 사용자 그룹.
    • worker_processes 지시어: 작업자 프로세스 동작 개수를 설정한다.
    • include 지시어: 지정된 파일을 인클루드시킨다.
  • 엔진엑스는 모듈 방식으로 동작하며, 각 모듈은 각각의 지시어를 갖고 있다. 대부분의 기본 지시어는 엔진엑스 핵심 모듈을 갖고 있다.

 

지시어 블록

중첩된 블록

ex) http 블록은 여러개의 server 블록을 선언하고 있다.

http {
	server {
		listen 80;
		server_name example.com;
		access_log /var/log/nginx/example.com.log;
		location ^~ /admin/ {
			index index.php;
		}
	}
}
  • server 블록: 서버 기기에서 돌아가는 웹사이트, 즉 가상 호스트를 구성한다. 호스트명이 example.com과 정확히 일치하는 HTTP 요청에 적용될 구성을 포함하고 있다.
  • location 블록: 지정된 경로와 일치할 때만 설정이 적용되게 하는 블록

💡구성이 하위 블록에 상속된다

  • server 블록 바로 안에 속한 access_log 지시어는 이 서버로 들어오는 모든 HTTP 요청을 텍스트 파일로 기록하게 한다. 이 구성은 location 블록에서도 유효하다.
  • 아래 예는 이렇게 location 블록에도 상속된 access_log 지시어를 비활성화 시키는 것을 보여준다. server 블록에서 지정된 값이 location 블록 수준에서 덮어써진 것이다. (/admin/ 경로를 제외한 웹 사이트의 모든 요청에 대해 로그가 활성화 된다)
...
	location ^~ /admin/ {
		index index.php;
		access_log off;
	}
...

 

고급 언어 규칙

지시어 값의 축약

파일 크기를 지정하는 지시어 값

  • k 또는 K:  킬로바이트
  • m 또는 M: 메가바이트
  • g 또는 G: 기가바이트
client_max_body_size 2G;
client_max_body_size 2048M;
client_max_body_size 2097152k;

💡 위 세 구문은 동일한 값을 갖는다.

 

시간을 지정하는 축약어

  • ms: 밀리초
  • s: 초
  • m: 분
  • h: 시간
  • d: 일(날)
  • w: 주
  • M: 달(30일)
  • y: 년(365일)
client_body_timeout 3m;
client_body_timeout 180s;
client_body_timeout 180;

💡 아무것도 붙이지 않았을 경우 기본 시간 단위는 초다.

client_body_timeout 1m30s;
client_body_timeout '1m 30s 500ms';

💡 서로 다른 단위의 값을 결합하는 것도 가능하다. (띄어쓰기로 구분할 때는 따옴표로 묶어야한다)

 

변수

  • 모듈은 지시어 값에 사용할 수 있는 변수를 제공한다.
    • ex) http 모듈은 $nginx_version 변수를 정의한다.
  • 엔진엑스의 변수는 항상 $표시로 시작한다.
  • log_format 지시어를 설정할 때 모든 종류의 변수를 포함시킬 수 있다.
log_format main '$pid - $nginx_version - $remote_addr';

 

 

기반 모듈(Base Module)의 지시어

엔진엑스 프로세스 아키텍처

기본 굿어 지시어를 살펴보기 전에 엔진엑스 데몬이 뒷단에서 동작하는 방식에 관련된 전반적인 프로세스 아키텍처를 이해할 필요가 있다.

 

엔진엑스를 시작하면 유일한 프로세스인 주 프로세스(master process)가 생기는데, 현재 사용자와 그룹의 권한으로 실행된다. 보통 root 사용자와 root 그룹 권한을 가진다. 주 프로세스는 클라이언트의 요청을 스스로 처리하지는 않고 대신 그 일을 처리해줄 작업자 프로세스(worker process)를 만든다. 작업자 프로세스는 별도로 정의한 사용자와 그룹으로 실행할 수 있다.

 

작업자 프로세스의 수, 작업자 프로세스당 최대 연결 수, 작업자 프로세스를 실행하는 사용자와 그룹 등을 구성 파일로 정의할 수 있다. 다음 명령어는 사용자 계정에서 2개의 작업자 프로세스를 가진 엔진엑스 프로그램의 예를 보여준다.

$ ps fuax | grep nginx
user    72806  0.0  0.0 112712   964 pts/0    S+   13:57   0:00              \_ grep --color=auto nginx
root       1178  0.0  0.0  22728  2344 ?        Ss   Jan11   0:00 nginx: master process /home/apps/nginx/sbin/./nginx
nobody    25573  0.0  0.0  23180  2480 ?        S    Jan16   0:09  \_ nginx: worker process
nobody    25574  0.0  0.0  23180  2336 ?        S    Jan16   0:03  \_ nginx: worker process

 

기반 모듈 소개

기반 모듈은 엔진엑스의 깁곤적인 기능을 가진 매개변수를 정의할 수 있는 지시어를 제공한다. 이 지시어들은 컴파일 때에도 비활성화할 수 없기 때문에 지시어와 블록은 항상 사용할 수 있다. 기반 모듈은 다음과 같은 세가지로 구분할 수 있다.

  • 핵심 모듈(core module): 프로세스 관리나 보안 같은 필수 기능 및 지시어로 이뤄진다.
  • 이벤트 모듈(event module): 네트워킹 기능의 내부 동작 방식을 구성한다.
  • 구성 모듈(configuration module): 구성을 외부 파일에서 가져와 포함시킨다.

 

핵심 모듈 지시어

대부분은 반드시 구성 파일의 최상위에 위치해야 하고 한 번만 사용할 수 있다. 일부 지시어는 여러 맥락에서 사용할 수 있다(ex. error_log)

지시어 이름 구문과 설명
user 구문: 
user username groupname;
user username;
기본값: 컴파일할 때 결정 됨.

구성 지시어로 정의되지 않으면 엔진엑스 주 프로세스의 사용자와 그룹이 사용된다. 엔진엑스 작업자 프로세스를 시작시키는 사용자 계정과 그룹을 지정할 수 있다. 그룹이 필수는 아니다. 보안상의 이유로 제한된 권한의 사용자와 그룹을 지정해야 하는데, 예를 들면 엔진엑스 전용의 사용자와 그룹을 만들고 서비스되는 파일에 적절한 권한을 적용하는 것이다.
worker_processes 구문: 숫자나 auto
worker_process 4;
기본값: 1

작업자 프로세스의 수를 지정한다. 엔진엑스는 요청 처리를 다수의 프로세스로 나눠준다. 기본값은 1이지만 CPU가 듀얼 코어 이상이라면 더 큰 값으로 지정하는 것이 좋다. 게다가 느린 I/O 수행으로 프로세스가 차단(block)되더라도 들어오는 요청을 다른 프로세스에 위임할 수 있다.다.
대신 엔진엑스가 이 지시어의 값을 적절히 선택하도록 auto를 사용할 수도 있다. 기본적으로 auto는 시스템에서 감지된 CPU 코어의 수가 된다.
pid 구문: 파일 경로
pid logs/nginx.pid
기본값: 컴파일할 때 결정된 값

엔진엑스 데몬의 pid 파일 경로다. 기본값은 컴파일할 때 결정된다. pid 파일은 운영체제에 종속적인 엔진엑스 init 스크립트에서 사용될 수 있기 때문에 이 지시어는 반드시 올바르게 설정돼야 한다.
error_log 구문:
error_log /file/path level;
기본값: logs/error.log error
맥락: main, http, mail, stream, server, location

level은 가장 상세한 로그를 남기는 debug부터 info, notice,warn, error, crit, alart 그리고 가장 치명적인 오류만 보고하는 emerg 중 하나로 지정할 수 있다.
오류 로그를 끄고 싶으면 로그 출력을 /dev/null로 지정하면 된다.
 error_log /dev/null crit;
파일 경로 대신 다른 것을 지정할 수도 있다. 표준 오류 출력 장치로 내보내고 싶으면 stederr, 시스템 로그로 보내고 싶으면 syslog, 메모리로 보내고 싶으면 memory로 지정할 수 있다.

 

이벤트 모듈

이벤트 모듈은 네트워크 메커니즘을 구성할 수 있는 지시어를 제공한다. 이벤트 모듈 지시어는 반드시 구성 파일의 최상위 수준에 있는 events 블록 안에 있어야 한다.

events {
	worker_connections 1024;
	...
}
지시어 이름 구문과 설명
worker_connections 구문: 숫자
 worker_cononections 1024;
기본값: 없음
작업자 프로세스가 동시에 처리할 수 있는 연결의 수를 지정한다.

* worker_connections: 이 설정은 보유한 하드웨어에 맞게 조정해야 한다. 더 많은 RAM과 고성능의 CPU를 가진 서버일수록 더 많은 동시 연결을 수용할 수 있다. 대용량 트래픽을 서비스하는 괴물 같은 서버라면 이 설정 값을 올리고 싶을 것이다.

 

서버 테스트

성능 테스트

Httperf

HP에서 개발되고 상대적으로 잘 알려진 오픈소스 도구며, 리눅스만 지원한다.

간단한 명령행 도구다. 각자 사용하는 OS의 기본 패키지 저장소에서도 구할 수 있을 것이다. 설치하고 나면 아래와 같이 명령을 실행할 수 있다.

httperf --server 192.168.1.10 --port 80 --uri /index.html --rate 300 --num-conn 30000 --num-call 1 --timeout 5

이 예에서 httperf는 http://192.168.1.10/index.html을 초당 300회 다운로드해서 결국 총 3,000개의 요청을 보낸다.

결과에는 응답 시간과 성공한 응답 횟수가 표시된다. 성공률이 100%이거나 응답 시간이 0ms에 가까우면 요청 비율을 높여서 서버가 취약점을 보일 때까지 테스트를 반복하자.

 

Autobench

펄로 httperf와 for를 래핑한 도구이며, 테스트 동작 방식을 개선하고 상세한 보고서를 생성하고자 만들어졌다.

오토벤치는 httperf를 더욱 효과적으로 사용하게 해주는 펄 스크립트다. 이 도구는 서버가 포화 상태가 될 때까지 요청 비율을 자동으로 높이면서 테스트를 계속 실행한다. 오토벤치의 인상적인 기능 하나는 .tsv 보고서를 생성하는 기능인데, 이 파일을 다양한 애플리케이션에서 열어 그래프를 생성할 수 있다.

 

OpenWebLoad

윈도우와 리눅스 모두를 지원하는 경량화된 오픈소스 부하 테스트 도구다.

오픈웹로드는 다른 접근법을 사용하는데, 서버에 요청 부하를 주고 얼마나 올바로 처리하는지 보는 대신 단순히 다양한 연결 횟구를 사용해 최대한 많은 요청을 보내고 나서 매초 리포트를 보여준다.

openload example.com/index/html 10

 

무중단 엔진엑스 업그레이드

  1. 기존 엔진엑스 실행 파일(/usr/local/nginx/sbin/nginx)을 새것으로 교체한다.
  2. ps x | grep nginx | grep master 명령이나 pid 파일의 값을 통해 엔진엑스 주 프로세스의 PID를 알아낸다.
  3. kill -USR2 PID 명령으로 USR2 신호를 주 프로세스에 보낸다. 이를 통해 기존 .pid 파일명이 바뀌고 새 실행 파일이 실행됨으로써 업그레이드가 시잦ㄱ될 것이다.
  4. kill -WINCH PID 명령으로 기존 주 프로세스에 WINCH 신호를 보낸다. 이를 통해 기존 작업자 프로세스들이 작업이 끝난 순서대로 점차 종료된다.
  5. 모든 기존 작업자 프로세스가 종료됐는지 확인한 후에 kill -QUIT PID 명령으로 기존 주 프로세스에 QUIT 신호를 보낸다.

 

 

 

 

참고) nginx.conf.default

# main 블록

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

# events 모듈이 제공하는 events 블록
events {
    worker_connections  1024; # events 모듈이 활성화한 지시어
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}
반응형