ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nginx] Worker Processes 알아보기
    Nginx 2023. 10. 6. 16:37
    728x90
    반응형

    - 목차

     

    들어가며.

    Nginx고성능의 Network IO 를 처리하기 위해서 Worker Process 를 사용합니다.

    구체적으로는 Master Process 와 Worker Process 들로 구성되어 클라이언트의 네트워크 요청을 처리하는데요.

    Master Process 는 클라이언트의 네트워크 연결 요청을 처리하고,

    Client - Server 사이의 Network Connection 은 Worker Process 에서 Read/Write 트래픽을 처리하게 됩니다.

     

    Master/Worker Process 에 대해서 확실히 이해하기 위해서는 TCP Network 에 대한 사전 지식이 필요합니다.

    TCP 연결은 일반적으로 2개의 Socket File 이 필요합니다.

    첫번째 Socket 은 Listening Socket 으로 이는 클라이언트와 서버 사이의 Network Connection 을 생성하는데에 사용됩니다.

    즉, 여러 클라이언트는 Nginx 와 네트워크 연결을 하기 위해서 Connection 을 맺죠.

    이것이 흔히 얘기하는 3-Way Handshake 에 해당합니다.

     

    3-Way Handshake 란 ?

    출처 : https://afteracademy.com/blog/what-is-a-tcp-3-way-handshake-process/

     

     

    3-Way Handshake 는 클라이언트와 서버 사이에 TCP 커넥션을 맺기 위해서 사용됩니다.

    Client 는 TCP/IP Packet 을 1개 생성합니다.

    이는 IP, Port 등의 서버의 위치 정보를 포함하며, 이 Packet 는 SYN 라는 정보를 내장합니다.

    이 패킷은 인터넷을 통해서 서버의 네트워크 내부로 전송됩니다.

     

    만약 서버가 클라이언트의 네트워크 요청을 처리할 준비가 되어있지 않다면,

    SYN 패킷은 적절히 처리되지 못하고 Client - Server 의 Connection 은 생성되지 않습니다.

    하지만 서버 측에서 Socket/Bind/Listen 등의 System Call 통해서 클라이언트의 네트워크 요청을 처리할 준비가 되어있다면,

    서버는 클라이언트에게 SYN/ACK 패킷을 전송합니다.

    이는 SYN/ACK 이라는 정보를 포함한 하나의 Packet 입니다.

     

    마지막으로 SYN/ACK 패킷을 전달받은 클라이언트는 서버에서 ACK 패킷을 전달합니다.

    이 과정에서 서버는 Accept System Call 을 사용해서 클라이언트와 서버 사이의 단독의 Connection 이 맺어집니다.

     

    Accepted Socket.

    서버는 3 Ways Handshake 과정을 마치게 되면 Client - Server 사이의 새로운 소켓을 생성합니다.

    이 소켓을 Accepted Socket 이라고 부르구요.

    이 소켓을 통해서 클라이언와 서버 사이의 통신이 이루어집니다.

    Read/Write, Send/Recv 등의 시스템 콜이 Accepted Socket 과 밀접한 관련이 있습니다.

     

    Nginx 에서 Worker Process 는 Accepted Socket 을 생성하고, 클라이언트와의 통신에 집중하게 되는 프로세스입니다.

    즉, Master ProcessListening Socket 을 통해서 클라이언트와의 연결을 위해서 동작하며,

    Worker Process 들은 Accepted Socket 을 통해서 클라이언트와의 데이터 교환에 집중합니다.

     

    아래의 이미지와 같은 구조로 Master Process 와 Worker Process 의 역할이 나뉘게 됩니다.

     

     

     

     

    Worker Process 란 ?

    Nginx 는 실행이 되면서 nginx.conf 에 작성된 설정대로 TCP Socket 을 생성합니다.

    "listen 80;" 와 같은 listen Directive 를 통해서 80 Port 를 리스닝하는 Listening Socket 을 생성하게 됩니다.

    이러한 과정은 Master Process 에서 실행이 되구요.

    Master Process 는 Client 의 연결 요청을 리스닝합니다.

     

    그리고 worker_processes Directive 의 설정값에 해당하는 수만큼 Worker Process 들을 생성합니다.

    worker_processes 는 일반적으로 auto 로 설정되어 Core 수만큼 Worker Process 들을 생성합니다.

    또는 구체적인 Worker Process 의 갯수를 명시할 수도 있습니다.

     

    fork 와 exec System Call.

    여기서 Worker Process 들이 어떻게 생성되는지 그 과정이 매우 중요합니다.

    Worker Process 는 Master Process 의 자식 프로세스로써 생성됩니다.

    그리고 fork 와 exec System Call 를 통해서 Master Process 를 복사하게 됩니다.

     

    먼저 실제로 Worker Process 가 Master Process 를 부모 프로세스로 가지는지 확인해보겠습니다.

    아래의 명령어들은 총 4개의 Worker Process 들을 생성하는 nginx.conf 와 Nginx Docker Container 를 실행하는 내용입니다.

     

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

     

    그리고 아래의 터미널 이미지는 "ps -ef" 명령어를 통해서 Master Process 와 Worker Process 의 관계를 확인하는 내용입니다.

    1개의 Master Process 와 4개의 Worker Process 들이 확인됩니다.

    그리고 4개의 Worker Process 들이 생성된 이유는 nginx.conf 의 worker_processes 의 값을 4 로 설정했기 때문입니다.

    이미지에서 확인할 수 있듯이 4개의 Worker ProcessPPID 가 모두 Master Process 의 PID 인 1 로 설정되어 있습니다.

     

    UID        PID  PPID  C STIME TTY          TIME CMD
    1001         1     0  0 02:51 ?        00:00:00 nginx: master process /opt/bitnami/nginx/sbin/nginx -c /opt/bitnami/nginx/conf/nginx.conf -g daemon off;
    1001        47     1  0 02:51 ?        00:00:00 nginx: worker process
    1001        48     1  0 02:51 ?        00:00:00 nginx: worker process
    1001        49     1  0 02:51 ?        00:00:00 nginx: worker process
    1001        50     1  0 02:51 ?        00:00:00 nginx: worker process
    root        51     0  0 02:52 pts/0    00:00:00 bash
    root        57    51  0 02:52 pts/0    00:00:00 ps -ef

     

     

    Worker Process 는 어떻게 Master Process 의 Socket 을 참조할까 ?

    아래의 함수 시그니처는 Accept System Call 의 시그니처를 간략하게 표현한 내용입니다.

    Accept 는 Socket File Descriptor 를 함수의 인자로 필요로 합니다.

     

    int accept(int sockfd);

     

     

    Accept System Call 이 필요로 하는 Socket 은 Master Process 가 가지는 Listening SocketFile Descriptor 인데요.

    이는 Worker Process 가 아닌 Master Process 가 가지고 있습니다.

    하지만 Worker Process 는 클라이언트와의 통신을 위햇 Accepted Socket 을 생성해야하며 이를 위해서 Listening SocketFile Descriptor 가 필요합니다.

     

    이러한 서로 다른 프로세스 간의 Socket File Descriptor 를 공유하기 위해서 Nginx 의 Worker Process 는 Master Process 의 자식 프로세스로써 생성됩니다.

    자식 프로세스는 부모 프로세스의 File Descriptor 목록을 상속받게 되는데요.

    이로써 자식 프로세스인 Worker Process 는 Listening Socket 에 기록되는 여러개의 클라이언트의 네트워크 요청을 전달받아서 Accepted Socket 을 생성할 수 있게 됩니다.

     

    정리하자면, Worker Process 는 클라이언트와 통신하기 위한 ( 연결 생성이 아님.!! ) Accepted Socket 을 생성해야하며,

    이를 위해서 상속된 Listening Socket File Descriptor 를 활용합니다.

     

    아래의 이미지는 Master Process 로부터 Socket File Descriptor 를 상속받는 Worker Process 의 관계를 구현한 자료입니다.

     

     

     

     

    worker_processes Directive.

    worker_processes Directive 를 통해서 Worker Process 의 갯수를 지정할 수 있습니다.

    기본 값은 worker_processes auto 로 설정됩니다.

    이는 서버의 Core 갯수만큼 Worker Process 를 생성하는 설정입니다.

     

    아래의 명령어는 worker_processes auto; 를 실험해보기 위한 nginx.conf 와 Docker Run 명령어입니다.

     

    cat <<'EOF'> /tmp/nginx.conf
    worker_processes auto;
    
    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 \
        --mount type=bind,source=/tmp/nginx.conf,target=/opt/bitnami/nginx/conf/nginx.conf \
        bitnami/nginx:1.24

     

    저는 아래와 같이 Docker Container 의 Core 를 3 으로 설정하였구요.

    생성되는 Worker Process 또한 3개의 프로세스가 생성됩니다.

     

    lscpu | grep Core
    Core(s) per cluster:                  3
    UID        PID  PPID  C STIME TTY          TIME CMD
    1001         1     0  0 04:54 ?        00:00:00 nginx: master process /opt/bitnami/nginx/sbin/nginx -c /op
    1001        47     1  0 04:54 ?        00:00:00 nginx: worker process
    1001        48     1  0 04:54 ?        00:00:00 nginx: worker process
    1001        49     1  0 04:54 ?        00:00:00 nginx: worker process

     

     

     

    반응형
Designed by Tistory.