10Gbps 서버에서 10,000개의 연결을 처리하도록 Linux 및 Nignx 조정

10Gbps 서버에서 10,000개의 연결을 처리하도록 Linux 및 Nignx 조정

CPU 코어 8개, 64GB RAM, 1TB NVMe를 갖춘 새로운 10Gbps 서버를 구입했습니다.

OS Centos 7.9 kernel 3.10.0-1160.36.2.el7.x86_64 also tried kernel-ml 5.13
SELinux is disabled.
firewalld and irqbalance stopped

iperf3를 이용하여 네트워크 테스트를 해본 결과 9.5Gbps 정도의 속도가 확인되었습니다.

그런 다음 10개의 1Gbps 서버를 사용하여 서버에서 정적 파일을 다운로드하는 또 다른 테스트를 수행한 결과, 서버는 거의 전체 10Gbps를 10개의 서버에 쉽게 푸시할 수 있었습니다.

그래서 우리는 Nginx를 사용하여 정적 파일을 다운로드하는 프로덕션 서비스 클라이언트에 서버를 배치했습니다. 최대 2,000개의 연결에 도달할 때까지 안정적인 성능을 제공할 수 있으며 이후 성능이 크게 떨어지기 시작합니다. 연결이 증가하면 트래픽이 감소하는 것을 볼 수 있으므로 4,000개 이상의 연결을 제공하면 2Gbps만 제공됩니다!

이미지 1은 트래픽과 HTTP를 보여줍니다.

가장 혼란스러운 점은 CPU가 거의 유휴 상태이고 RAM이 비어 있으며 NVMe 및 대용량 RAM 덕분에 IO 사용량이 낮다는 것입니다. 그러나 서버에 수천 개의 연결이 있으면 모든 서비스에서 속도가 느려집니다. HTTP, FTP, SSH 심지어 yum 업데이트에도 시간이 너무 오래 걸립니다 응답할 시간입니다. 네트워크나 패킷의 정체 또는 커널이나 NIC의 일부 제한처럼 보입니다.

htop 맨 위 로드

대부분의 튜닝 팁을 시도해 보았습니다.

ifconfig eth0 txqueuelen 20000
ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 00:16:3e:c2:f5:21  txqueuelen 20000  (Ethernet)
        RX packets 26012067560  bytes 1665662731749 (1.5 TiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 30684216747  bytes 79033055227212 (71.8 TiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tc -s -d qdisc 쇼 dev eth0

qdisc mq 1: root
    Sent 7733649086021 bytes 1012203012 pkt (dropped 0, overlimits 0 requeues 169567)
    backlog 4107556b 2803p requeues 169567
qdisc pfifo_fast 0: parent 1:8 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 2503685906926 bytes 1714686297 pkt (dropped 0, overlimits 0 requeues 1447)
    backlog 4107556b 2803p requeues 1447
qdisc pfifo_fast 0: parent 1:7 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 532876060762 bytes 366663805 pkt (dropped 0, overlimits 0 requeues 7790)
    backlog 0b 0p requeues 7790
qdisc pfifo_fast 0: parent 1:6 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 563510390106 bytes 387948990 pkt (dropped 0, overlimits 0 requeues 9694)
    backlog 0b 0p requeues 9694
qdisc pfifo_fast 0: parent 1:5 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 563033712946 bytes 387564038 pkt (dropped 0, overlimits 0 requeues 10259)
    backlog 0b 0p requeues 10259
qdisc pfifo_fast 0: parent 1:4 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 562982455659 bytes 387451904 pkt (dropped 0, overlimits 0 requeues 10706)
    backlog 0b 0p requeues 10706
qdisc pfifo_fast 0: parent 1:3 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 559557988260 bytes 385263948 pkt (dropped 0, overlimits 0 requeues 9983)
    backlog 0b 0p requeues 9983
qdisc pfifo_fast 0: parent 1:2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 528903326344 bytes 364105031 pkt (dropped 0, overlimits 0 requeues 7718)
    backlog 0b 0p requeues 7718
qdisc pfifo_fast 0: parent 1:1 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
    Sent 1919099245018 bytes 1313486295 pkt (dropped 0, overlimits 0 requeues 111970)
    backlog 0b 0p requeues 111970

ethtool -k eth0

Features for eth0:
rx-checksumming: on [fixed]
tx-checksumming: on
        tx-checksum-ipv4: off [fixed]
        tx-checksum-ip-generic: on
        tx-checksum-ipv6: off [fixed]
        tx-checksum-fcoe-crc: off [fixed]
        tx-checksum-sctp: off [fixed]
scatter-gather: on
        tx-scatter-gather: on
        tx-scatter-gather-fraglist: off [fixed]
tcp-segmentation-offload: off
        tx-tcp-segmentation: off
        tx-tcp-ecn-segmentation: off
        tx-tcp6-segmentation: off
        tx-tcp-mangleid-segmentation: off
udp-fragmentation-offload: on
generic-segmentation-offload: off
generic-receive-offload: off
large-receive-offload: off [fixed]
rx-vlan-offload: off [fixed]
tx-vlan-offload: off [fixed]
ntuple-filters: off [fixed]
receive-hashing: off [fixed]
highdma: on [fixed]
rx-vlan-filter: on [fixed]
vlan-challenged: off [fixed]
tx-lockless: off [fixed]
netns-local: off [fixed]
tx-gso-robust: off [fixed]
tx-fcoe-segmentation: off [fixed]
tx-gre-segmentation: off [fixed]
tx-ipip-segmentation: off [fixed]
tx-sit-segmentation: off [fixed]
tx-udp_tnl-segmentation: off [fixed]
fcoe-mtu: off [fixed]
tx-nocache-copy: off
loopback: off [fixed]
rx-fcs: off [fixed]
rx-all: off [fixed]
tx-vlan-stag-hw-insert: off [fixed]
rx-vlan-stag-hw-parse: off [fixed]
rx-vlan-stag-filter: off [fixed]
busy-poll: off [fixed]
tx-gre-csum-segmentation: off [fixed]
tx-udp_tnl-csum-segmentation: off [fixed]
tx-gso-partial: off [fixed]
tx-sctp-segmentation: off [fixed]
rx-gro-hw: off [fixed]
l2-fwd-offload: off [fixed]
hw-tc-offload: off [fixed]
rx-udp_tunnel-port-offload: off [fixed]

sysctl -p

vm.max_map_count = 1048575
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_ecn = 0
net.ipv4.tcp_sack = 1
net.ipv4.tcp_syncookies = 0
net.ipv4.conf.all.log_martians = 1
vm.swappiness = 10
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65536
net.core.netdev_max_backlog = 250000
fs.file-max = 100000
net.ipv4.ip_local_port_range = 13000 65000
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
net.ipv4.tcp_slow_start_after_idle = 0
net.core.rmem_max = 2147483647
net.core.rmem_default = 2147483647
net.core.wmem_max = 2147483647
net.core.wmem_default = 2147483647
net.core.optmem_max = 2147483647
net.ipv4.tcp_rmem = 4096 87380 2147483647
net.ipv4.tcp_wmem = 4096 65536 2147483647
net.ipv4.tcp_low_latency = 1
net.ipv4.tcp_adv_win_scale = 1
net.ipv4.tcp_keepalive_time = 60
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 5
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.netfilter.nf_conntrack_max = 655360
net.netfilter.nf_conntrack_tcp_timeout_established = 10800
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

ulimit -a

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 256680
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 100000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 100000
cpu time               (seconds, -t) unlimited
max user processes              (-u) 100000
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

nginx.conf

worker_processes        auto;
worker_rlimit_nofile    100000;

thread_pool default threads=256     max_queue=65536;

events {
    worker_connections  65536;
    worker_aio_requests 65536;
    multi_accept on;
    accept_mutex on;
    use epoll;
}

http {
    server_tokens off;
    server_names_hash_max_size      4096;
    server_names_hash_bucket_size   128;

    tcp_nopush     on;
    tcp_nodelay     on;
    client_body_timeout 12;
    client_header_timeout 12;
    keepalive_timeout 15;
    keepalive_requests 1000;
    send_timeout 10;

    aio                         threads=default;
    sendfile                    on;
    sendfile_max_chunk          512k;
    open_file_cache             max=100000  inactive=10m;
    open_file_cache_valid       10m;
    open_file_cache_min_uses    10;
    open_file_cache_errors      on;

    gzip  off;
}

따라서 질문은: 정적 파일을 다운로드하는 10Gbps 트래픽으로 10k 연결을 제공하는 방법은 무엇입니까? Linux, nginx 또는 하드웨어의 문제입니까?

답변1

Brandon이 이미 답변했습니다. irqbalance를 켭니다. numad를 실행하고 조정하세요. 튜닝이 필요한 특정 워크로드가 없다면 튜닝을 중단하세요. 배포하기 전에 2000~10000개의 요청을 테스트한 작업 테스트 결과는 어디에 있습니까? 이 문제는 프로덕션 환경에서 발생해서는 안 됩니다. 테스트를 통해 분명히 식별되었을 것입니다. 실제 사용에서는 흔히 발생하지 않는 버그가 발견되는 경우가 많지만 대부분의 구성 및 애플리케이션 버그는 테스트 중에 식별되고 수정될 수 있습니다. irq 선호도에 관해 사용할 수 있는 문서가 많이 있습니다. 귀하의 사용 사례가 내장된 튜닝 도구를 사용하는 것보다 더 나은 결과를 얻을 수 있을지 의문입니다. 아마도 손으로 튜닝하는 경우 성능이 더 나쁠 것입니다.

답변2

의 출력은 top커널이 들어오는 모든 연결의 소프트 인터럽트로 넘쳐난다고 말합니다. 연결이 너무 빨리 진행되어 네트워크 카드에 의해 트리거된 하드웨어 인터럽트가 커널이 처리할 수 있는 것보다 더 빠르게 소프트 인터럽트를 대기열에 추가합니다. 이것이 CPU, RAM 및 IO 사용량이 너무 낮은 이유입니다. 들어오는 연결로 인해 시스템이 계속 중단됩니다. 여기에 필요한 것은 로드 밸런서입니다.

관련 정보