nginx.png

Nginx는 경량 웹 서버이다.

클라이언트로부터 요청을 받았을 때 요청에 맞는 정적 파일을 응답해주는 HTTP Web Server로 활용되기도 하고, Reverse Proxy Server로 활용하여 WAS 서버의 부하를 줄일 수 있는 로드 밸런서로 활용되기도 한다.


1. Nginx 흐름

nginxflow.png

Nginx는 Event-Driven 구조로 동작하기 때문에 한 개 또는 고정된 프로세스만 생성하여 사용하고,비동기 방식으로 요청들을 Concurrency 하게 처리할 수 있다.

위의 그림에서 보이듯이 Nginx는 새로운 요청이 들어오더라도 새로운 프로세스와 쓰레드를 생성하지 않기 때문에 프로세스와 쓰레드 생성 비용이 존재하지 않고,

적은 자원으로도 효율적인 운용이 가능하다.

이러한 Nginx의 장점 덕분에 단일 서버에서도 동시에 많은 연결을 처리할 수 있다.

apache 의 C10K 문제점 해결(한 시스템에 동시 접속자수가 1만명이 넘어갈 때 효율적방안)을 위해 만들어진 Event-Driven 구조의 웹서버SW 라고 합니다. OSI7 Layer 중 application Level 아래의 Level 에서 Nginx 같은 웹서버가 HTTP 통신을 담당합니다.


2. Nginx의 구조

nginxstructure.png

Nginx는 하나의 Master Process와 다수의 Worker Process로 구성되어 실행된다.

Master Process는 설정 파일을 읽고, 유효성을 검사 및 Worker Process를 관리한다.

모든 요청은 Worker Process에서 처리한다. Nginx는 이벤트 기반 모델을 사용하고, Worker Process 사이에 요청을 효율적으로 분배하기 위해 OS에 의존적인 메커니즘을 사용한다.

Worker Process의 개수는 설정 파일에서 정의되며, 정의된 프로세스 개수와 사용 가능한 CPU 코어 숫자에 맞게 자동으로 조정된다.


3. 프록시 설정

한 웹 서버 안에는 여러 서버가 있을 수 있다.

그 각각의 서버들도 자기의 서버가 있고 웹서버 안에 있는 이상 메인도메인(퍼블릭 ip) 안에서 프라이빗 ip를 가지고 있는 것이다.

프록시 설정을 하면 퍼블릭 ip를 거친 요청만이 프라이빗 ip로의 요청 마무리를 통해 요청을 통한 원하는 응답을 가질 수 있다.

클라이언트가 서버의 자원을 자기 맘대로 쥐락펴락 못하려면 웹서버의 퍼블릭 ip, 웹 서버 안에서의 프라이빗 ip 를 모두알면 안된다.

클라이언트는 퍼블릭 ip만 알고있는 상황에서 요청을 하고, 이 퍼블릭 ip를 거치는 과정에서 여러 보안적 이슈를 해결할 수 있다.

그 다음에 프록시의 역할, 즉 요청하는 프라이빗 ip로의 연결을 대리(proxy)하는것이 바로 프록시 서버의 역할이다.

여기서의 보안적 장점, 그리고 안전한 요청만을 받아 웹 서버 안에서 자동으로 요청하는 서버 ip로 연결해준다는 것에서 프록시 설정이 중요해지는 것이다.


4. 로드밸런싱

로드밸런싱도 프록시와 원리는 비슷하다.

웹 서버의 퍼블릭 ip(DNS)로의 요청을 받아 웹 서버 안에서 원하는 서버에다가 그 요청을 전달하는 것이다.

하지만 문맥, 필요한 상황이 정해져있다.

바로 요청들을 웹 서버 안에서 서로 다른 여러 서버에다가 나눈다는 것이 아니고

한 웹서버에 같은 서버를 여러개 배치(쌍둥이)하고 수많은 클라이언트의 같은 자원 요청했을 때,

한 서버에다 그 요청을 링크하는것이 아니고 여러개의 같은 서버(쌍둥이)에다가 그 요청들을 나누는 것이다.

어차피 그 서버들은 쌍둥이, 즉 같은 내용이기 때문에 응답또한 당연히 같다.

중복, 반복되는 요청을 여러 같은 서버들이 나누어 전담함으로써 과부하로 인한 서버에러를 피할 수 있는 것이다.

#nginx.conf

upstream server-proxy { //로드밸런싱 블록, 이름을 server-proxy 로 설정하였다.
        server 15x.xxx.xxx.x1:8090;
        server 15x.xxx.xxx.x2:8090;
}
server {
        listen 8443 ssl http2;
        server_name xxxxxxxx.com;
        location / {
                proxy_pass http://server-proxy; //upstream에서 설정한 로드밸런싱 이름을 적는다.
        }
}


5. Nginx 에러 해결하기

엔진엑스에서 마주친 에러와 해결방법에 대해 기록해두려 한다.

Nginx 413 (request entity too large)

error : failed to load resource the server responded with a status of 413 (request entity too large)

nginx 서버 업로드 크기 설정하기

nginx의 파일 업로드 크기를 정해야합니다. 설정되지 않은 경우 1M가 넘는 경우 에러가 발생할 수 있습니다. 기본 사이즈의 경우 1Mbyte로 알고 있는데 특이한 점이 개발서버와 운영서버에 설정이 같음에도 개발서버에서는 에러가 발생하지 않더군요. nginx 설정 파일은 둘 다 확인했을때 동일하였던 점을 생각하면 다른 파일이나 버전등에 영향이 있지 않을까 생각됩니다. 어쨌든 이유를 막론 nginx의 허용사이즈를 설정하는 방법은 어떻게할까요?

$ vi /sw/nginx/nginx.conf

설정된 부분으로 이동한 후 http { 내용 } 부분에 해당 속성과 값을 추가하거나 변경하도록 합니다. 이때 client_max_body_size 속성과 값을 설정해야합니다. 그럼 직접 수정해보도록하겠습니다. 예를들어 아래와 같이 값을 설정합니다. 만약 100Mbyte를 허용하는 경우라면 아래와 같겠죠.

#nginx.conf
http {
  # Set client upload size - 100Mbyte
  client_max_body_size 100M;
  ...
  ..
  .
}

이제 업로드 크기가 설정되었습니다. nginx를 재시작합니다.

nginx -s reload

또는 service를 재시작할 수도 있겠죠.

service nginx restart

여기까지 수정 후 파일을 업로드 해보았습니다. 좀 전까지 1M 이상 파일 업로드시 에러가 발생했던 부분이 정상적으로 잘 동작하는군요! 이제 파일 업로드의 에러가 해결되었습니다.


Nginx 504 (Gateway Time-out)

nginx를 사용하다 보면 504 Gateway Time-out Error 가 발생할 때가 있다.

그 이유는 서버와 클라이언트간 proxy 연결 시간이 default인 60초를 넘어서 나타나는 것이다.

이를 해결하기 위한 방법은 아주 간단하다. server에서 설정을 바꿔주면 된다.

default인 60초를 넉넉하게 300초로 바꿔주면 해결!

#nginx.conf

server {   
  listen 8443 ssl http2;   
  server_name XXXXXXXX.com;   
  location / {      
    proxy_pass http://server-proxy;      
    proxy_connect_timeout 300;      
    proxy_send_timeout 300;      
    proxy_read_timeout 300;      
    send_timeout 300;   
    }
}