我目前有一个高流量的 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 服务器是实际的瓶颈,并且带宽、服务器之间的任何网络硬件和后端都没有问题。
确保启用 HTTP/2(我看到您已经启用了)和 TLSv1.3。使用 TLSv1.3 而不是 TLSv1.2 时,您可以获得小幅改进,但效果是可衡量的。检查此博客文章由 Netflix 提供
使用默认的 proxy_buffering (“on”)。更多信息这里。
访问日志:我猜想您的磁盘正在遭受重创。更改访问日志的格式以减少写入(或将其设置为“关闭”)。
启用对上游服务器的 keepalive。更多信息这里。
使用 ethtool 设置(增加)网络接口的 Rx/Tx 值 - 一定要检查一下。Serverfault 问题这里。最大值为 4096。我的默认值为 256。我只能更改 2 个接口之一的值。像这样更改它(本例中我的接口名称为 enp6s0):
ethtool -G enp6s0 rx 4096 tx 4096
内核参数:
尝试设置 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)。
编辑:忘记了交易队列的长度。
- 事务队列长度 - 使用 将默认值 1000 增加到 5000 或 10000。
ifconfig ${interface} txqueuelen ${size}
建议用于所有高吞吐量服务器。放入 /etc/rc.local 以在重启后保留。
编辑2:更多!
- 额外的 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
- 压缩相关点(更适用于每天有大量新用户、提供静态内容的网站)
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 供应商会根据当前负载自动增加服务器数量。