Thursday, January 9, 2025

Giải thích về F-Stack Nginx APP theo tài liệu hướng dẫn

-

1. Mở đầu.

Ở trong bài triển khai F-Stack Nginx ở trước đó mình đã có giải thích sơ qua rồi, nhưng bài này mình sẽ đi chi tiết hơn về lý thuyết bám sát tài liệu của tác giả.

2. Tổng quan về F-Stack.

  • F-Stack là một framework mạng mã nguồn mở dựa trên DPDK (Data Plane Development Kit).
  • Nó cải thiện hiệu năng xử lý gói tin bằng cách chạy các tác vụ mạng trong không gian người dùng (user-space) thay vì kernel.
  • F-Stack hỗ trợ Nginx làm HTTP framework, giúp các ứng dụng web sử dụng giao thức HTTP dễ dàng tích hợp với F-Stack.

3. Kiến trúc Nginx sử dụng F-Stack.

Kiến trúc của Nginx tích hợp với F-Stack được mô tả như sau:

  • Master Process:
    • Điều khiển các tín hiệu như cập nhật lại cấu hình (reload) hoặc thoát (quit).
    • Tạo và quản lý các worker process.
  • Worker Process:
    • Mỗi worker process sẽ xử lý các kết nối mạng và request HTTP/HTTPS.
    • Primary Worker được tạo đầu tiên để thiết lập cơ chế hoạt động với F-Stack.
    • Secondary Workers được khởi tạo sau khi Primary Worker sẵn sàng.
  • F-Stack Handling:
    • Các worker process tích hợp thêm khả năng xử lý F-Stack thông qua các hàm:
      • ff_init() – Khởi tạo F-Stack.
      • ff_run(worker_process_cycle) – Chạy vòng lặp xử lý của worker process, bao gồm cả sự kiện F-Stack và kernel.

Giải thích sơ đồ Nginx tích hợp F-Stack.

Cấu trúc tổng thể.

Sơ đồ mô tả cách Nginx tích hợp với F-Stack xử lý yêu cầu từ bên ngoài theo cơ chế đa tiến trình (multi-process):


                                                        +--------+
                         +------------------------+     |
                            channel: socketpair         |
                         +------------------------+     |  signal(reload, quit..)
                                                        |
                                                        |
                                              +---------v--------+
                                              |                  |
                             +----------------+  master process  +---------------+
                             |                |                  |               |
                             |  channel       +----------+-------+               |
                             |                           |              channel  |
                             |                  channel  |                       |
                             |                           |                       |
                   +---------+----------+     +----------+--------+    +---------+--------+
first one to start |                    |     |                   |    |                  |
 last one to exit<-+   primary worker   |     |  secondary worker |    | secondary worker |
                   |                    |     |                   |    |                  |
                   +--------------------+     +-------------------+    +------------------+
                   +--------------------+     +-------------------+  
                   |                    |     |                   |
                   |   fstack,kernel    |     |   fstack,kernel   |
                   |     and channel    |     |     and channel   |
                   |     loop thread    |     |     loop thread   |
                   |                    |     |			  |
                   +--------------------+     +-------------------+
                    woker process cycle        woker process cycle
  • Master Process:
    • Chịu trách nhiệm:
      • Quản lý các tín hiệu điều khiển như reload, quit.
      • Tạo và giám sát các worker process.
    • Sử dụng channel (cơ chế liên lạc giữa các tiến trình, thường là socketpair) để giao tiếp với các worker process.
  • Worker Process:
    • Chịu trách nhiệm xử lý các kết nối mạng, bao gồm:
      • Primary Worker:
        • Tiến trình worker đầu tiên được khởi tạo.
        • Thiết lập và đảm bảo F-Stack hoạt động đúng cách.
        • Là tiến trình cuối cùng kết thúc khi Nginx dừng hoạt động.
      • Secondary Workers:
        • Các tiến trình worker bổ sung để xử lý nhiều kết nối đồng thời.
        • Tất cả các worker đều xử lý request theo vòng lặp (worker process cycle).
  • F-Stack và Kernel:
    • F-Stack:
      • Xử lý các gói tin trong user-space (thay vì kernel), giúp tăng hiệu năng mạng.
    • Kernel:
      • Một số tác vụ nhất định (nếu cấu hình kernel_network_stack on) sẽ được xử lý qua stack mạng của kernel.
    • Các worker có thể xử lý cả sự kiện từ kernelF-Stack, tùy thuộc vào cấu hình.

Quy trình xử lý yêu cầu.

Dưới đây là quy trình xử lý khi có một request đến Nginx tích hợp F-Stack:

  • Request đến từ Client:
    • Ví dụ: Một trình duyệt gửi request đến server qua http://example.com.
  • Master Process không xử lý trực tiếp request:
    • Master process chỉ giao nhiệm vụ cho các worker process qua cơ chế channel.
  • Worker Process nhận request:
    • Request sẽ được nhận bởi một trong các worker process (Primary hoặc Secondary).
    • Worker process kiểm tra cấu hình:
      • Nếu request dành cho kernel network stack (khi kernel_network_stack on): Request sẽ được xử lý qua kernel.
      • Nếu request dành cho F-Stack: Request sẽ được xử lý hoàn toàn trong user-space qua F-Stack.
  • Xử lý request với F-Stack:
    • F-Stack sử dụng vòng lặp sự kiện (event loop) để xử lý:
      • Nhận gói tin từ card mạng thông qua DPDK.
      • Phân tích và xử lý HTTP (thông qua Nginx).
      • Tạo response và gửi lại qua F-Stack.
  • Response gửi lại Client:
    • Sau khi hoàn thành xử lý, worker gửi phản hồi qua F-Stack hoặc kernel (tùy cấu hình) trở lại client.

Ví dụ minh họa với 1 request.

Bối cảnh:

  • Server sử dụng Nginx tích hợp F-Stack.
  • Cấu hình:
    • Port 80, 443 được xử lý qua F-Stack (kernel_network_stack off).
    • Port 22 (SSH) được xử lý qua kernel (kernel_network_stack on).

Quy trình:

  • Request đến server:
    • Một trình duyệt gửi HTTP request đến http://example.com qua port 80.
    • Request được nhận bởi card mạng (NIC).
  • F-Stack nhận request:
    • Worker process của Nginx nhận gói tin qua F-Stack (do port 80 được cấu hình sử dụng F-Stack).
    • Worker phân tích gói tin HTTP.
  • Xử lý request:
    • Worker process kiểm tra cấu hình Nginx (ví dụ: tìm file hoặc nội dung cần phản hồi).
    • Nếu là một file tĩnh, Nginx truy cập hệ thống file để lấy dữ liệu.
    • Nếu là một yêu cầu proxy, Nginx chuyển tiếp qua proxy backend (nếu được cấu hình).
  • Gửi phản hồi:
    • Worker tạo response HTTP.
    • Response được gửi lại qua F-Stack đến card mạng và trả về client.

Trường hợp khác (port 22):

  • Nếu có một kết nối SSH qua port 22:
    • Request được chuyển thẳng đến kernel network stack vì F-Stack không xử lý SSH.
    • Kernel xử lý kết nối SSH và phản hồi client.

Ý nghĩa của vòng lặp xử lý (Worker Process Cycle)

  • Worker Process Cycle là vòng lặp chính để worker process xử lý:
    • Channel: Lắng nghe và phản hồi tín hiệu từ Master Process.
    • F-Stack và Kernel: Xử lý các sự kiện mạng dựa trên cấu hình (như nhận gói tin, phân tích HTTP, gửi phản hồi).
  • Với F-Stack, vòng lặp này tối ưu hiệu năng xử lý gói tin qua user-space.

Tóm tắt quy trình.

BướcHoạt động
1. Nhận requestGói tin từ client được nhận qua NIC và chuyển vào F-Stack hoặc kernel tùy cấu hình.
2. Phân tíchWorker process phân tích và xử lý yêu cầu (HTTP hoặc proxy).
3. Tạo phản hồiWorker process tạo response dựa trên cấu hình và dữ liệu được yêu cầu.
4. Gửi responseResponse được gửi lại client qua F-Stack hoặc kernel.

4. Điểm khác biệt khi tích hợp F-Stack.

F-Stack thêm một số chỉ thị mới vào cấu hình Nginx khi NGX_HAVE_FSTACK được định nghĩa.

  • kernel_network_stack:
    • Mục đích: Quyết định server sử dụng kernel network stack hay F-Stack.
    • Cách dùng:
kernel_network_stack on;  # Sử dụng kernel network stack.
kernel_network_stack off; # Sử dụng F-Stack (mặc định).

proxy_kernel_network_stack:

  • Mục đích: Quyết định proxy (trong các block http, stream, mail, hoặc server) sử dụng kernel network stack hay F-Stack.
  • Cách dùng:
proxy_kernel_network_stack on;  # Proxy sử dụng kernel network stack.
proxy_kernel_network_stack off; # Proxy sử dụng F-Stack (mặc định).

schedule_timeout:

  • Mục đích: Thiết lập khoảng thời gian polling để tương tác với kernel network stack.
  • Cách dùng:
schedule_timeout 30ms; # Giá trị mặc định là 30ms.

5. Thay đổi cấu hình cần thiết.

Một số thay đổi quan trọng trong file cấu hình nginx.conf khi sử dụng F-Stack:

  • user root;:
    • Tài khoản root cần thiết để F-Stack hoạt động vì DPDK yêu cầu quyền root để tương tác trực tiếp với phần cứng mạng.
  • fstack_conf f-stack.conf;:
    • Chỉ định đường dẫn file cấu hình F-Stack (f-stack.conf), mặc định nằm trong $NGX_PREFIX/conf/f-stack.conf.
  • worker_processes:
    • Phải bằng với số lõi CPU (lcore) được chỉ định trong dpdk.lcore_mask của file cấu hình f-stack.conf.
  • Block events:
    • worker_connections 102400;: Tăng số lượng kết nối có thể xử lý đồng thời.
    • use kqueue;: Sử dụng cơ chế sự kiện kqueue (trên FreeBSD hoặc macOS).
  • sendfile off;:
    • Tắt tính năng sendfile để tương thích với F-Stack (vì tính năng này dựa vào kernel network stack).

Với file nginx.conf.

Các tùy chọn cài đặt này bạn có thể xem trong file cấu hình Nginx, ví dụ của mình đang đặt ở đây /usr/local/nginx_fstack/conf/nginx.conf .

Dưới đây là phiên bản tối ưu và đầy đủ của file cấu hình Nginx, đảm bảo tương thích với F-Stack. Cấu hình này được chỉnh sửa để tối ưu hiệu suất và tuân thủ các yêu cầu đặc biệt của F-Stack.

cat > /usr/local/nginx_fstack/conf/nginx.conf << 'OEF'
user root;
worker_processes 1;                                     # Cần phù hợp với dpdk.lcore_mask trong f-stack.conf
fstack_conf /usr/local/nginx_fstack/conf/f-stack.conf;  # Đường dẫn chính xác tới f-stack.conf

events {
    worker_connections 102400;          # Tăng giới hạn kết nối đồng thời
    use kqueue;                         # Cần thiết để tương thích với F-Stack
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile off;                       # Bắt buộc phải tắt sendfile cho F-Stack
    keepalive_timeout 65;

    # Log cấu hình, giúp giám sát
    access_log /var/log/nginx/access.log combined;
    error_log /var/log/nginx/error.log error;

    # Tăng giới hạn kích thước request
    client_max_body_size 2048m;

    # Server chính chạy trên port 80
    server {
        listen 80;                      # Lắng nghe trên port 80
        server_name hoanghd.com;

        root /home/www/;                # Thư mục gốc của website
        index index.html;               # File mặc định
        charset utf-8;

        location / {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_buffering on;

            # Timeout tối ưu cho request dài
            proxy_connect_timeout 30s;
            proxy_read_timeout 30s;
            proxy_send_timeout 30s;
            send_timeout 30s;

            # Tăng cường bảo mật
            add_header Content-Security-Policy upgrade-insecure-requests;
        }
    }
}
OEF

Với file f-stack.conf.

Đảm bảo rằng file f-stack.conf tương thích với cấu hình Nginx. Dưới đây là ví dụ cơ bản:

cat > /usr/local/nginx_fstack/conf/f-stack.conf << 'OEF'
[dpdk]
lcore_mask=1
channel=4
promiscuous=1
numa_on=1
nb_mbufs=65535
rx_mbufs=2048
tx_mbufs=2048
tx_csum_offoad_skip=0
tso=0
vlan_strip=1
idle_sleep=0
pkt_tx_delay=100
symmetric_rss=0
port_list=0
nb_vdev=0
nb_bond=0

[pcap]
enable = 0
snaplen= 96
savelen= 16777216

[port0]
addr=10.237.7.79
netmask=255.255.255.0
broadcast=10.237.7.255
gateway=10.237.7.1

[kni]
enable=1
method=reject
tcp_port=80,443

[freebsd.boot]
hz=100
fd_reserve=1024
kern.ipc.maxsockets=262144
net.inet.tcp.syncache.hashsize=4096
net.inet.tcp.syncache.bucketlimit=100
net.inet.tcp.tcbhashsize=65536
kern.ncallout=262144
kern.features.inet6=1
net.inet6.ip6.auto_linklocal=1
net.inet6.ip6.accept_rtadv=2
net.inet6.icmp6.rediraccept=1
net.inet6.ip6.forwarding=0

[freebsd.sysctl]
kern.ipc.somaxconn=32768
kern.ipc.maxsockbuf=16777216
net.link.ether.inet.maxhold=5
net.inet.tcp.fast_finwait2_recycle=1
net.inet.tcp.sendspace=16384
net.inet.tcp.recvspace=8192
net.inet.tcp.cc.algorithm=cubic
net.inet.tcp.sendbuf_max=16777216
net.inet.tcp.recvbuf_max=16777216
net.inet.tcp.sendbuf_auto=1
net.inet.tcp.recvbuf_auto=1
net.inet.tcp.sendbuf_inc=16384
net.inet.tcp.recvbuf_inc=524288
net.inet.tcp.sack.enable=1
net.inet.tcp.blackhole=1
net.inet.tcp.msl=2000
net.inet.tcp.delayed_ack=0
net.inet.udp.blackhole=1
net.inet.ip.redirect=0
net.inet.ip.forwarding=0
OEF

Hoặc bạn có thể tách ra nhiều file config theo nhu cầu với block [stack], đây là một tùy chọn để cung cấp thêm cấu hình chi tiết hơn cho các tham số của network stack. Nếu không có phần này, F-Stack sẽ sử dụng các giá trị mặc định đã được định nghĩa trong mã nguồn hoặc trong các file cấu hình DPDK.

Ví dụ ở dưới đây mình vẫn giữ cấu hình trên nhưng mình tách [freebsd.sysctl] ra một file riêng, lúc đó file f-stack.conf chính bạn chỉ cần khai báo thêm block [stack] với conf=/usr/local/nginx_fstack/conf/stack-custom.conf là đường dẫn đến file chứa block [freebsd.sysctl] nhé.

cat > /usr/local/nginx_fstack/conf/stack-custom.conf << 'OEF'
[dpdk]
lcore_mask=1
channel=4
promiscuous=1
numa_on=1
nb_mbufs=65535
rx_mbufs=2048
tx_mbufs=2048
tx_csum_offoad_skip=0
tso=0
vlan_strip=1
idle_sleep=0
pkt_tx_delay=100
symmetric_rss=0
port_list=0
nb_vdev=0
nb_bond=0

[pcap]
enable = 0
snaplen= 96
savelen= 16777216

[port0]
addr=10.237.7.79
netmask=255.255.255.0
broadcast=10.237.7.255
gateway=10.237.7.1

[kni]
enable=1
method=reject
tcp_port=80,443

[freebsd.boot]
hz=100
fd_reserve=1024
kern.ipc.maxsockets=262144
net.inet.tcp.syncache.hashsize=4096
net.inet.tcp.syncache.bucketlimit=100
net.inet.tcp.tcbhashsize=65536
kern.ncallout=262144
kern.features.inet6=1
net.inet6.ip6.auto_linklocal=1
net.inet6.ip6.accept_rtadv=2
net.inet6.icmp6.rediraccept=1
net.inet6.ip6.forwarding=0

[stack]
conf=/usr/local/nginx_fstack/conf/stack-custom.conf
OEF

Đây là file chứa nội dung config /usr/local/nginx_fstack/conf/stack-custom.conf của block [freebsd.sysctl].

cat > /usr/local/nginx_fstack/conf/stack-custom.conf << 'OEF'
[freebsd.sysctl]
kern.ipc.somaxconn=32768
kern.ipc.maxsockbuf=16777216
net.link.ether.inet.maxhold=5
net.inet.tcp.fast_finwait2_recycle=1
net.inet.tcp.sendspace=16384
net.inet.tcp.recvspace=8192
net.inet.tcp.cc.algorithm=cubic
net.inet.tcp.sendbuf_max=16777216
net.inet.tcp.recvbuf_max=16777216
net.inet.tcp.sendbuf_auto=1
net.inet.tcp.recvbuf_auto=1
net.inet.tcp.sendbuf_inc=16384
net.inet.tcp.recvbuf_inc=524288
net.inet.tcp.sack.enable=1
net.inet.tcp.blackhole=1
net.inet.tcp.msl=2000
net.inet.tcp.delayed_ack=0
net.inet.udp.blackhole=1
net.inet.ip.redirect=0
net.inet.ip.forwarding=0
OEF

Tối ưu hóa

  • F-Stack Configuration
    • Xác định dpdk.port_list tương ứng với giao diện mạng được sử dụng.
    • Đảm bảo card mạng hỗ trợ DPDK và đã bind đúng với vfio-pci.
  • Hệ thống log
    • Tăng quyền ghi log để tránh lỗi khi ghi:
mkdir -p /var/log/nginx/
chmod 644 /var/log/nginx/*.log
  • Hiệu suất
    • Sử dụng cấu hình worker_connections cao để hỗ trợ nhiều kết nối đồng thời.
    • Đảm bảo keepalive_timeout vừa đủ để tránh giữ kết nối quá lâu.
  • Kiểm tra tính tương thích
    • Sau khi khởi động Nginx, kiểm tra log /var/log/nginx/error.log/var/log/f-stack.log để xác nhận F-Stack đang chạy.

Khởi động Nginx.

Check cấu hình, nếu không có lỗi, bạn sẽ thấy dòng syntax is ok.

shell> /usr/local/nginx_fstack/sbin/nginx -t
nginx: the configuration file /usr/local/nginx_fstack/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx_fstack/conf/nginx.conf test is successful

Khởi động Nginx.

/usr/local/nginx_fstack/sbin/nginx -s stop
/usr/local/nginx_fstack/sbin/nginx

Kiểm tra dịch vụ Nginx.

shell> ps -aef | grep nginx
root       24849       1  0 01:44 ?        00:00:00 nginx: master process /usr/local/nginx_fstack/sbin/nginx
root       24850   24849 99 01:44 ?        06:04:25 nginx: worker process
root       25354   22170  0 07:49 pts/2    00:00:00 grep nginx

Với cấu hình này, Nginx sẽ chạy trên nền F-Stack và được tối ưu để xử lý nhiều kết nối với độ trễ thấp.

6. Quá trình biên dịch Nginx với F-Stack.

Để tích hợp F-Stack, bạn cần biên dịch lại Nginx:

  • Lệnh cấu hình (configure):
./configure --prefix=/usr/local/nginx_fstack --with-ff_module
  • --prefix=/usr/local/nginx_fstack: Đường dẫn cài đặt Nginx tích hợp F-Stack.
  • --with-ff_module: Bật module F-Stack.

Biên dịch và cài đặt:

make
make install

7. Kết luận.

Khi sử dụng Nginx với F-Stack:

  • F-Stack thay thế kernel network stack, xử lý trực tiếp các gói tin trong user-space để đạt hiệu năng cao hơn.
  • File cấu hình cần thay đổi để tối ưu với F-Stack (ví dụ: tắt sendfile, tăng worker_connections).
  • Một số chỉ thị mới (kernel_network_stack, proxy_kernel_network_stack, schedule_timeout) cho phép điều chỉnh cách Nginx tương tác với F-Stack và kernel network stack.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories