ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nginx] Worker Connections 알아보기
    Nginx 2024. 2. 4. 07:53
    728x90
    반응형

    - 목차

     

    들어가며.

    이번 글에서 Nginx 의 Worker Connections 에 대해서 알아보려고 합니다.

    Nginx 의 Worker Connections 는 Master Process 와 Worker Process 의 차이점과 역할에 대한 배경 지식이 필요합니다.

    아래 링크의 컨텐츠를 참고하시면 도움이 될 것 같네요.

     

    https://westlife0615.tistory.com/337

     

    [Nginx] Worker Processes 알아보기

    - 목차 들어가며.Nginx 는 고성능의 Network IO 를 처리하기 위해서 Worker Process 를 사용합니다.구체적으로는 Master Process 와 Worker Process 들로 구성되어 클라이언트의 네트워크 요청을 처리하는데요.Mas

    westlife0615.tistory.com

     

    NginxWorker ProcessClient 와 Backend 와 실질적인 데이터 교환을 수행합니다.

    이때의 Client 는 TCP 커넥션을 맺은 Client 를 의미하며,

    Backend 는 Nginx 가 Reverse Proxy 로써 동작할 때에 네트워크 요청을 포워딩해야하는 다른 서버를 의미합니다.

     

    이처럼 Worker Process 는 클라이언트의 수가 많아질수록 또는 포워딩해야하는 Backend 서버가 많아질수록

    Worker Process 가 소화해야하는 Connection 의 숫자가 많아져야합니다.

     

    Nginx 는 worker_connections 라는 디렉티브를 제공하며, 이 worker_connections 디렉티브를 통해서 하나의 Worker Process 가 생성할 수 있는 최대의 Connection 의 숫자를 지정할 수 있습니다.

     

    Worker Connection 이란 무엇인가 ?

    그럼 Worker Connection 이라는 것이 정확히 무엇일까요 ?

    Worker ConnectionTCP Socket 을 의미합니다.

    즉, Accept System Call 을 통해서 생성되는 TCP Socket 에 해당하며 동시에 100개의 Client 가 네트워크 요청을 보내면

    Nginx 의 Worker Process 는 100개의 TCP Socket 을 생성할 수 있어야 합니다.

     

    이때 nginx.confworker_connections 의 설정값을 통해서 하나의 Worker Process 가 동시에 생성할 수 있는 TCP Socket 의 갯수는 제한됩니다.

    그래서 일반적으로 Nginx 가 한번에 처리할 수 있는 요청의 수는 worker_processes x worker_connections 만큼의 값만큼 동시 처리를 수행할 수 있다고 합니다.

    왜냐하면 worker_processes 디렉티브의 값만큼 Worker Process 가 생성되고,

    하나의 Worker Processworker_connections 디렉티브의 값만큼 TCP Socket 을 생성할 수 있기 때문이죠.

     

    우선 간단히 Worker Connection 이 어떻게 동작하는지 확인해보겠습니다.

    아래의 코드들은 1개의 Worker Process 를 생성하도록 지정한 nginx.conf 파일과 nginx 를 실행하는 Docker 명령어입니다.

     

    cat <<'EOF'> /tmp/nginx.conf
    worker_processes 1;
    
    events {
        worker_connections 1024;
        multi_accept on;
    }
    
    http {
      server {
          listen 80;
    
          location / {
              return 200 $request_uri;
          }
      }
    }
    EOF
    
    docker run --platform linux/arm64 -d -p 8080:80 \
        --name nginx \
        --user root \
        --mount type=bind,source=/tmp/nginx.conf,target=/opt/bitnami/nginx/conf/nginx.conf \
        bitnami/nginx:1.24

     

     

    그리고 생성된 Nginx 를 향해서 GET 요청을 전송합니다.

     

    curl http://localhost:8080

     

    lsof 명령어를 통해서 Worker Process 의 File Descriptor 상태를 확인합니다.

    ( 참고로 저의 경우에는 Worker Process 의 PID 가 57 입니다.

    그리고 lsof 는 프로세스와 관련된 File 들의 목록을 나열하는 명령어입니다. )

    lsof -p 57

     

    lsof 의 결과는 아래와 같이 2개의 Socket 이 확인됩니다.

    80 포트는 Master Process 로부터 상속받은 Listening Socket 을 의미합니다.

    그리고 ESTABLISHED 로 표현된 Socket 이 Client 와 연결된 Accepted Socket 을 의미합니다.

    이렇게 총 2개의 Socket 이 만들어지게 됩니다.

     

    COMMAND PID   USER   FD      TYPE             DEVICE SIZE/OFF   NODE NAME
    nginx    57 nobody    3u     IPv4             231596      0t0    TCP e152a46f0969:80->172.17.0.1:57664 (ESTABLISHED)
    nginx    57 nobody    6u     IPv4             201887      0t0    TCP *:80 (LISTEN)

     

    위 Accepted Socket 에 대해서 잠시 분석을 해보면,

    • TYPE IPv4 : IPv6 와 IPv4 중에서 IPv4 의 IP 프로토콜을 사용
    • Node TCP : TCP 와 UDP 중에서 TCP 프로토콜을 사용한다는 의미이며, HTTP 요청 또한 내부적으로 TCP 통신을 반드시 수행합니다.
    • e152a46f0969:80->172.17.0.1:57664
      1. e152a46f0969 는 Nginx 의 IP 를 지칭하며, 이는 Docker Container 내부에서 동작하기 때문에 이러한 별칭이 연결됨.
      2. 80 포트는 Nginx 가 사용하는 Port 번호를 의미함.
      3. 172.17.0.1 는 클라이언트의 IP 를 의미하며, 현재의 경우에는 Docker Bridge Network 의 IP 로 지정됩니다.
      4. 57664 또한 클라이언트의 Port 를 의미하는데, IP 와 마찬가지로 Docker Bridge Network 의 임시 Port 가 지정되었습니다.

     

     

    Nginx 가 Reverse Proxy 로써 동작한다면 ?

    만약 Nginx 가 Reverse Proxy 로써 동작한다면 1번의 네트워크 연결 시에 Worker Connection 는 2개씩 생성됩니다.

    그 이유는 Client - Nginx 그리고 Nginx - Backend Server 와 같이 2개의 TCP Socket 이 필요하기 때문입니다.

     

    아래의 코드는 Nginx 가 Reverse Proxy 로 동작할 때에 Worker Connection 이 2개씩 생성되는 상황을 확인하기 위한 명령어입니다.

     

    cat <<'EOF'> /tmp/nginx.conf
    worker_processes 1;
    
    events {
        worker_connections 1024;
        multi_accept on;
    }
    
    http {
      server {
          listen 80;
    
          location /delay {
              proxy_pass http://delay:80;
          }
      }
    }
    EOF
    
    docker network create nginx-net
    
    docker run --platform linux/arm64 -d -p 8080:80 \
        --name nginx \
        --network nginx-net \
        --user root \
        --mount type=bind,source=/tmp/nginx.conf,target=/opt/bitnami/nginx/conf/nginx.conf \
        bitnami/nginx:1.24
    
    docker run --network nginx-net -d \
      --name delay \
      --hostname delay \
      kennethreitz/httpbin

     

    위의 명령어를 실행시켜 2개의 Docker Container 를 실행합니다.

    실행 후 생성된 서버들의 네트워크 구조를 아래의 이미지와 같습니다.

     

     

    그리고 아래의 HTTP GET 요청을 통해서 생성되는 Worker Connection 을 확인해봅니다.

     

    curl http://localhost:8080/delay/10

     

     

    아래와 같이 생성되는 Accepted Socket 은 2개가 관찰됩니다.

    하나의 Socket 은 Client -> Nginx 의 Socket.

    다른 하나는 Nginx -> Backend Server 로의 Socket.

     

    COMMAND PID   USER   FD      TYPE             DEVICE SIZE/OFF   NODE NAME
    nginx    57 nobody    3u     IPv4             257095      0t0    TCP 6e4d43dbde8e:80->172.23.0.1:64568 (ESTABLISHED)
    nginx    57 nobody    6u     IPv4             253459      0t0    TCP *:80 (LISTEN)
    nginx    57 nobody   10u     IPv4             256116      0t0    TCP 6e4d43dbde8e:36368->delay.nginx-net:80 (ESTABLISHED)

     

     

    worker_connections 디렉티브 알아보기.

    nginx.conf 파일은 worker_connections 디렉티브를 제공합니다.

    worker_connections 지시자를 통해서 하나의 Worker Process 가 생성할 수 있는 최대 Connection 갯수를 제한할 수 있습니다.

     

    우선 아래와 같이 worker_connections 이 4 인 Nginx 를 실행해보도록 하겠습니다.

    참고로 아래의 구성은 Nginx 가 Reverse Proxy 로써 동작하기 때문에 하나의 연결 당 2개의 Worker Connection 이 생성됩니다.

     

    cat <<'EOF'> /tmp/nginx.conf
    worker_processes 1;
    
    events {
        worker_connections 4;
        multi_accept on;
    }
    
    http {
      server {
          listen 80;
    
          location /delay {
              proxy_pass http://delay:80;
          }
      }
    }
    EOF
    
    docker network create nginx-net
    
    docker run --platform linux/arm64 -d -p 8080:80 \
        --name nginx \
        --network nginx-net \
        --user root \
        --mount type=bind,source=/tmp/nginx.conf,target=/opt/bitnami/nginx/conf/nginx.conf \
        bitnami/nginx:1.24
    
    docker run --network nginx-net -d \
      --name delay \
      --hostname delay \
      kennethreitz/httpbin

     

     

    그리고 아래와 같이 HTTP Get 요청을 통해서 최대값이 지정된 Worker Connections 의 동작을 확인할 수 있습니다.

     

    curl http://localhost:8080/delay/10

     

    아래의 결과는 1초 간격을 HTTP GET 요청에 대한 Nginx 의 Socket 상태를 확인하는 출력인데요.

    아래의 결과처럼 매 요청마다 NginxWorker Process 는 새로운 2개의 Socket 을 생성하며,

    각 Socket 마다 새로운 Port 로 연결이 됩니다.

     

    그리고 최대 2개의 Accepted Socket 를 생성하지 못합니다.

    그래서 worker_connections 지시자의 설정값과 넉넉히 설정해서 다수의 Client 와 Backend Server 와의 데이터 교환에 차질이 없도록 해야합니다.

     

     

    반면 worker_connections 의 값을 넉넉히 설정할 경우에 아래의 결과처럼 많은 수의 TCP Socket File Descriptor 들이 확인됩니다.

     

     

     

     

    반응형
Designed by Tistory.