NGINX là HTTP server phổ biến nhất trên thế giới. NGINX có kiến trúc "master" - "worker", với master process làm nhiệm vụ quản lý, và các worker process sẽ nhận các HTTP request và xử lý.

NGINX worker_processes là gì

Số lượng worker process được set bằng config directive: worker_processes mặc định là 1, và có thể "tự động" với từ khóa auto.

Syntax:     worker_processes number | auto;
Default:

worker_processes 1;

Context:    main

Defines the number of worker processes.

The optimal value depends on many factors including (but not limited to) the number of CPU cores, the number of hard disk drives that store data, and load pattern. When one is in doubt, setting it to the number of available CPU cores would be a good start (the value auto will try to autodetect it).

    The auto parameter is supported starting from versions 1.3.8 and 1.2.5.

https://nginx.org/en/docs/ngx_core_module.html#worker_processes

khi set auto, NGINX sẽ try to autodetect - cố tìm số "available CPU cores", dễ dàng xem số CPU trên máy với câu lệnh

$ nproc
4

hay file /proc/cpuinfo

$ grep processor /proc/cpuinfo
processor   : 0
processor   : 1
processor   : 2
processor   : 3

auto là bao nhiêu?

"auto" là bao nhiêu? lấy giá trị từ đâu? có đọc từ /proc ra không? thử đọc code C xem viết gì:

$ git clone --depth 1 https://github.com/nginx/nginx --branch release-1.27.1
Cloning into 'nginx'...
remote: Enumerating objects: 555, done.
...
Note: switching to 'e06bdbd4a20912c5223d7c6c6e2b3f0d6086c928'.
...

$ cd nginx
$ grep -Rn 'define NGINX_VERSION' src/core/nginx.h
13:#define NGINX_VERSION      "1.27.1"

Tìm từ khóa auto:

$ grep -Rin '"auto"'
...
src/core/nginx.c:1425:    if (ngx_strcmp(value[1].data, "auto") == 0) {
src/core/nginx.c:1566:    if (ngx_strcmp(value[1].data, "auto") == 0) {
...

Mở src/core/nginx.c tìm "auto" thấy:

static char *
ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_str_t        *value;
    ngx_core_conf_t  *ccf;

    ccf = (ngx_core_conf_t *) conf;

    if (ccf->worker_processes != NGX_CONF_UNSET) {
        return "is duplicate";
    }

    value = cf->args->elts;

    if (ngx_strcmp(value[1].data, "auto") == 0) {
        ccf->worker_processes = ngx_ncpu;
        return NGX_CONF_OK;
    }

    ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);

    if (ccf->worker_processes == NGX_ERROR) {
        return "invalid value";
    }

    return NGX_CONF_OK;
}

nếu đọc từ config được giá trị là "auto", NGINX sẽ gán ccf->worker_processes = ngx_ncpu.

Tìm ngx_ncpu:

$ grep -Rn ngx_ncpu
src/os/win32/ngx_os.h:59:extern ngx_uint_t   ngx_ncpu;
src/os/win32/ngx_win32_init.c:14:ngx_uint_t  ngx_ncpu;
src/os/win32/ngx_win32_init.c:131:    ngx_ncpu = si.dwNumberOfProcessors;
src/os/unix/ngx_os.h:79:extern ngx_int_t    ngx_ncpu;
src/os/unix/ngx_posix_init.c:13:ngx_int_t   ngx_ncpu;
src/os/unix/ngx_posix_init.c:62:    if (ngx_ncpu == 0) {
src/os/unix/ngx_posix_init.c:63:        ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
src/os/unix/ngx_posix_init.c:67:    if (ngx_ncpu < 1) {
src/os/unix/ngx_posix_init.c:68:        ngx_ncpu = 1;
src/os/unix/ngx_freebsd_init.c:210:        ngx_ncpu = ngx_freebsd_hw_ncpu / 2;
src/os/unix/ngx_freebsd_init.c:213:        ngx_ncpu = ngx_freebsd_hw_ncpu;
src/os/unix/ngx_darwin_init.c:164:    ngx_ncpu = ngx_darwin_hw_ncpu;
...

thấy trên các hệ điều hành, NGINX sẽ lấy giá trị theo cách khác nhau. Trên "posix" như các Linux-based OS, NGINX gọi C function sysconf(_SC_NPROCESSORS_ONLN).

man sysconf

NAME
       sysconf - get configuration information at run time

SYNOPSIS
       #include <unistd.h>
...
- _SC_NPROCESSORS_ONLN
      The number of processors currently online (available).  See also get_nprocs_conf(3).

Viết 1 chương trình C 5 dòng để in ra giá trị này:

// main.c
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("online CPUs %ld\n", sysconf(_SC_NPROCESSORS_ONLN));
}

// $ cc main.c  # compile C code to a.out file
// $ ./a.out
// online CPUs 4

Dùng strace xem sysconf thực sự đọc từ đâu:

$ strace ./a.out 2>&1 | grep open
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
$ cat /sys/devices/system/cpu/online
0-3

Vậy NGINX lấy giá trị được tính bởi sysconf, đọc từ file /sys/devices/system/cpu/online.

Trong container, NGINX auto dùng mấy worker process?

Nếu dùng podman xem link này để có thể dùng option --cpus, docker không cần chỉnh gì:

--cpus float                               Number of CPUs. The default is 0.000 which means no limit

Trong container

$ podman run --cpus=1 -it docker.io/nginx bash

#root@1f334076d74f:/ nginx &
[1] 2
2024/08/28 13:19:04 [notice] 2#2: using the "epoll" event method
2024/08/28 13:19:04 [notice] 2#2: nginx/1.27.1
2024/08/28 13:19:04 [notice] 2#2: built by gcc 12.2.0 (Debian 12.2.0-14)
2024/08/28 13:19:04 [notice] 2#2: OS: Linux 6.8.0-40-generic
2024/08/28 13:19:04 [notice] 2#2: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/08/28 13:19:04 [notice] 3#3: start worker processes
2024/08/28 13:19:04 [notice] 3#3: start worker process 4
2024/08/28 13:19:04 [notice] 3#3: start worker process 5
2024/08/28 13:19:04 [notice] 3#3: start worker process 6
2024/08/28 13:19:04 [notice] 3#3: start worker process 7

[1]+  Done                    nginx
# apt update && apt install -y procps python
...
# ps xau | grep nginx
root           3  0.0  0.0  11404  1892 ?        Ss   13:19   0:00 nginx: master process nginx
nginx          4  0.0  0.0  11872  3044 ?        S    13:19   0:00 nginx: worker process
nginx          5  0.0  0.0  11872  3044 ?        S    13:19   0:00 nginx: worker process
nginx          6  0.0  0.0  11872  3044 ?        S    13:19   0:00 nginx: worker process
nginx          7  0.0  0.0  11872  3044 ?        S    13:19   0:00 nginx: worker process
# nproc
4
# cat /sys/devices/system/cpu/online
0-3

Nội dung file này được mang từ máy host vào, vì vậy dù container được set bao nhiêu CPU thì NGINX (hay các ngôn ngữ lập trình ví dụ Python) vẫn đọc giá trị là số CPU của máy host.

# python3
Python 3.11.2 (main, Aug 26 2024, 07:20:54) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.cpu_count()
4

Kết luận

NGINX hay các ngôn ngữ lập trình khi chạy trong container đếm số CPU của máy host, không phải giá trị CPU request/limit cấp cho container.

Hết.

HVN at http://pymi.vn and https://www.familug.org.

Ủng hộ tác giả 🍺



Published

Category

frontpage

Tags

Contact