由于套接字缓冲区溢出,从接收队列中删除数据包

由于套接字缓冲区溢出,从接收队列中删除数据包

我目前有一个高流量的 nginx 服务器。通常情况下,其中一个请求运行缓慢或延迟,而另一个请求运行正常。

当我运行时watch -d --no-title -n4 'netstat -s | egrep -i "lock|socket\ buf"',我得到以下输出:

    118804 packets pruned from receive queue because of socket buffer overrun
    1 ICMP packets dropped because socket was locked
    10648 delayed acks further delayed because of locked socket

在我的/etc/sysctl.conf我有以下内容:

fs.file-max = 70000
vm.overcommit_memory=1
net.core.somaxconn=165535
net.core.wmem_default=2129920

我也尝试了这个配置,但结果是一样的:

fs.file-max = 70000
vm.overcommit_memory=1
net.core.somaxconn=165535
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 65536 33554432
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_syn_retries = 3
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_fin_timeout = 10

该盒子是一个 40 核盒子,运行带有 nginx 1.18 的 ubuntu 20,并且相关的 nginx 配置如下所示:

user user;
worker_processes auto;
pid /run/nginx.pid;
worker_rlimit_nofile 25000;
events {
        worker_connections 1024;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##
        access_log off;
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 0;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        #limit_req_zone $binary_remote_addr zone=mylimit:100m rate=10r/m;
        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";
        ##
        # Virtual Host Configs
        ##
        upstream backend {
            least_conn;
            server 1.2.3.4:3292 fail_timeout=0 weight=1;
            server 1.2.3.5:3292 fail_timeout=0 weight=1;
            server 1.2.3.6:3292 fail_timeout=0 weight=1;    
            server 1.2.3.7:3292 fail_timeout=0 weight=1;


        }
        server {
            listen      80;
            server_name dvr.example.com;
            location / {
                return 301 https://$server_name$request_uri;
            }
        }
        server {
            listen 443 ssl http2 default_server;
            server_name dvr.example.com;
            ssl on;
            ssl_certificate /etc/letsencrypt/live/dvr.example.com-0001/fullchain.pem; # managed by Certbot
            ssl_certificate_key /etc/letsencrypt/live/dvr.example.com-0001/privkey.pem; # managed by Certbot

            location = / {
                 return 301 https://example.com;
            }

            location / {
                #limit_req zone=mylimit burst=20;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_read_timeout 3600;
                proxy_request_buffering off;
                proxy_buffering off;
                proxy_pass http://backend;

             }

            location /nginx_status {
                 # Turn on stats
                 stub_status on;
                 access_log   off;
                 # only allow access from 192.168.1.5 #
                 #allow 192.168.1.5;
                 #deny all;
             }
        }
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

任何关于如何解决这个问题的帮助都将不胜感激。另外需要注意的是,根据nload

编辑:评论中要求的内容

$ sudo cat /proc/net/protocols
protocol  size sockets  memory press maxhdr  slab module     cl co di ac io in de sh ss gs se re sp bi br ha uh gp em
AF_VSOCK  1136      0      -1   NI       0   yes  vmw_vsock_vmci_transport  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n
PACKET    1344      1      -1   NI       0   no   kernel      n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n
PINGv6    1112      0      -1   NI       0   yes  kernel      y  y  y  n  n  y  y  n  y  y  y  y  n  y  y  y  y  y  n
RAWv6     1112      1      -1   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  n  y  y  y  y  n  n
UDPLITEv6 1216      0       2   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  n  n  n  y  y  y  n
UDPv6     1216      1       2   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  n  n  n  y  y  y  n
TCPv6     2160    233   77165   no     320   yes  kernel      y  y  y  y  y  y  y  y  y  y  y  y  y  n  y  y  y  y  y
UNIX      1024    209      -1   NI       0   yes  kernel      n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n
UDP-Lite  1024      0       2   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  y  n  n  y  y  y  n
PING       904      0      -1   NI       0   yes  kernel      y  y  y  n  n  y  n  n  y  y  y  y  n  y  y  y  y  y  n
RAW        912      0      -1   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  n  y  y  y  y  n  n
UDP       1024      1       2   NI       0   yes  kernel      y  y  y  n  y  y  y  n  y  y  y  y  y  n  n  y  y  y  n
TCP       2000   1658   77168   no     320   yes  kernel      y  y  y  y  y  y  y  y  y  y  y  y  y  n  y  y  y  y  y
NETLINK   1040     16      -1   NI       0   no   kernel      n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n  n

接下来

$ ip -s link show ens160
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:3f:af:19 brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast   
    9479594446622 8365661139 0       110     0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    9300082049967 4894324603 0       0       0       0   

最后一个

sudo netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:https           0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdom:8000 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdom:6380 0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:http            0.0.0.0:*               LISTEN     
tcp        0      0 localhost:domain        0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN     
tcp        0      0 localhost.lo:postgresql 0.0.0.0:*               LISTEN     
tcp6       0      0 [::]:3193               [::]:*                  LISTEN     
tcp6       0      0 [::]:3290               [::]:*                  LISTEN     
tcp6       0      0 [::]:3180               [::]:*                  LISTEN     
tcp6       0      0 localhost6.localdo:6380 [::]:*                  LISTEN     
tcp6       0      0 [::]:http               [::]:*                  LISTEN     
tcp6       0      0 [::]:3187               [::]:*                  LISTEN     
tcp6       0      0 [::]:3188               [::]:*                  LISTEN     
tcp6       0      0 [::]:3189               [::]:*                  LISTEN     
tcp6       0      0 [::]:3190               [::]:*                  LISTEN     
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN     
tcp6       0      0 [::]:3191               [::]:*                  LISTEN     
tcp6       0      0 [::]:3192               [::]:*                  LISTEN     
tcp6       0      0 localhost6.l:postgresql [::]:*                  LISTEN     
udp        0      0 localhost:domain        0.0.0.0:*                          
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7          
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     SEQPACKET  LISTENING     50111    /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     12835653 /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     12835657 /run/user/1000/snapd-session-agent.socket
unix  2      [ ACC ]     STREAM     LISTENING     12835658 /run/user/1000/gnupg/S.gpg-agent.browser
unix  2      [ ACC ]     STREAM     LISTENING     12835659 /run/user/1000/gnupg/S.gpg-agent
unix  2      [ ACC ]     STREAM     LISTENING     12835660 /run/user/1000/bus
unix  2      [ ACC ]     STREAM     LISTENING     12835661 /run/user/1000/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING     12835662 /run/user/1000/gnupg/S.gpg-agent.extra
unix  2      [ ACC ]     STREAM     LISTENING     12835663 /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING     51487    @irqbalance1397.sock
unix  2      [ ACC ]     STREAM     LISTENING     50082    /run/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING     50099    /run/lvm/lvmetad.socket
unix  2      [ ACC ]     STREAM     LISTENING     50101    /run/systemd/journal/stdout
unix  2      [ ACC ]     STREAM     LISTENING     26678    /run/lvm/lvmpolld.socket
unix  2      [ ACC ]     STREAM     LISTENING     39064    /var/lib/lxd/unix.socket
unix  2      [ ACC ]     STREAM     LISTENING     13067    /var/run/vmware/guestServicePipe
unix  2      [ ACC ]     STREAM     LISTENING     39055    /run/snapd.socket
unix  2      [ ACC ]     STREAM     LISTENING     39057    /run/snapd-snap.socket
unix  2      [ ACC ]     STREAM     LISTENING     39060    /run/acpid.socket
unix  2      [ ACC ]     STREAM     LISTENING     39062    /run/uuidd/request
unix  2      [ ACC ]     STREAM     LISTENING     39066    /var/run/dbus/system_bus_socket
unix  2      [ ACC ]     STREAM     LISTENING     36990    /var/run/postgresql/.s.PGSQL.5432
unix  2      [ ACC ]     STREAM     LISTENING     40264    /var/run/supervisor.sock.1365
unix  2      [ ACC ]     STREAM     LISTENING     39059    @ISCSIADM_ABSTRACT_NAMESPACE

nginx 状态选项卡显示

Active connections: 947 
server accepts handled requests
 826649 826649 1261546 
Reading: 0 Writing: 640 Waiting: 352 

答案1

我对这个话题很感兴趣,但不幸的是我没有任何使用如此大带宽的代理(因此,我自己无法测试)。我很想知道这些是否对您有帮助。

我们假设 nginx 服务器是实际的瓶颈,并且带宽、服务器之间的任何网络硬件和后端都没有问题。

  1. 确保启用 HTTP/2(我看到您已经启用了)和 TLSv1.3。使用 TLSv1.3 而不是 TLSv1.2 时,您可以获得小幅改进,但效果是可衡量的。检查此博客文章由 Netflix 提供

  2. 使用默认的 proxy_buffering (“on”)。更多信息这里

  3. 访问日志:我猜想您的磁盘正在遭受重创。更改访问日志的格式以减少写入(或将其设置为“关闭”)。

  4. 启用对上游服务器的 keepalive。更多信息这里

  5. 使用 ethtool 设置(增加)网络接口的 Rx/Tx 值 - 一定要检查一下。Serverfault 问题这里。最大值为 4096。我的默认值为 256。我只能更改 2 个接口之一的值。像这样更改它(本例中我的接口名称为 enp6s0):

    ethtool -G enp6s0 rx 4096 tx 4096

  6. 内核参数:

  • 尝试设置 net.ipv4.tcp_mem 为总 tcp 内存。我认为这应该大于 net.ipv4.tcp_wmem 和 net.ipv4.tcp_rmem。

  • net.core.rmem/wmem - 尝试设置最小值和默认值,而不仅仅是最大值

    net.core.rmem_default=262144

    net.core.wmem_default=262144

  • 检查一下邮政用于设置最佳 rmem_max 值(您可以尝试 262144)。

编辑:忘记了交易队列的长度。

  1. 事务队列长度 - 使用 将默认值 1000 增加到 5000 或 10000。ifconfig ${interface} txqueuelen ${size}建议用于所有高吞吐量服务器。放入 /etc/rc.local 以在重启后保留。

编辑2:更多!

  1. 额外的 nginx 参数:
  • 减少超时:

client_body_timeout 30

client_header_timeout 30

keepalive_timeout 30

send_timeout 30

  • 增加缓冲区大小:

client_body_buffer_size 32K

client_header_buffer_size 2k

large_client_header_buffers 8 16k

  1. 压缩相关点(更适用于每天有大量新用户、提供静态内容的网站)

9.1. gzip压缩参数:

  • 添加 gzip_min_length 以避免压缩小文件。我将其设置为 2048 左右(以字节为单位的值)。
  • gzip_comp_level - 默认为 6。如果您更担心 CPU 而不是带宽,请将其降低到级别 1 或 2。您仍可以通过更少的 CPU 工作获得大部分减少的带宽优势。

9.2. brotli压缩:

  • 考虑添加 brotli 压缩(要么用 brotli 替换 gzip,要么同时启用两者)。不确定解压和压缩是否真的比 gzip 更快,但它确实能更好地压缩文件。

9.3. 静态压缩:

  • 人们不知道/不使用这个功能绝对是犯罪行为。您可以提供预压缩的静态文件,而不是动态压缩它们。

9.4. 补充要点:

  • 如果您对压缩音频文件感兴趣,我想提一下 .opus 有损压缩算法,例如 discord 使用的算法。Opus 应该取代 .mp3,但我还没有看到它发生……一探究竟

答案2

使用资源占用超过 100% 的服务器通常不是一个好主意。您有 1500 个用户正在并行下载非常大的视频文件,而您只使用一个 nginx 服务器来处理它。

尽管您的巨型服务器有 40 个核心,但某些组件并非无限,例如主板总线、RAM、磁盘、网络适配器等。这些都会导致瓶颈,影响服务器的反应能力。在我看来,目前您已经达到了硬件的极限。

通过更好地调整 nginx,您可以获得一些额外的效率,但您可能需要比这更大的改进。

由于 nginx 服务器只负责平衡与其他后端服务器的连接负载,因此您可以通过复制此 nginx 服务器轻松扩展您的网站。

您可能会发现,多台功能有限(且更便宜)的 nginx 服务器可能比一台巨型服务器更有效。互联网上的计算机集群倾向于使用多个较小的节点,而不是几个非常大的节点。一些 VPS 供应商会根据当前负载自动增加服务器数量。

相关内容