尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

NGINX Plus在Ubuntu 20.04上的百万级并发配置与调优实践

NGINX Plus在Ubuntu 20.04上的百万级并发配置与调优实践 聊一个我在运维一线经常被问到的问题NGINX Plus在Ubuntu 20.04上到底怎么配才能撑住百万级并发访问说实话百万并发这四个字在网上已经被说滥了但真正扛过大促流量、压测到CPU打满的情况很多人其实没经历过。NGINX Plus作为商业版解决的不只是性能问题更重要的是在高负载场景下给你一个可控、可观测、可从容操作的基础设施入口。这篇文章我把最近一次项目的完整思路梳理出来覆盖系统参数预调优、Plus安装、upstream配置、核心调优参数的计算逻辑、压测方法、常见坑点以及真正逼近百万并发时你在架构层面必须做的选择。适合正在做高并发架构、想从开源Nginx迁移到Plus、或者压测时发现怎么调都上不去的朋友这篇应该能帮你省不少试错时间。1. 项目背景与整体设计思路1.1 为什么选NGINX Plus而不是继续用开源版很多团队的第一反应是开源版Nginx已经很能打了为什么还要花钱买Plus这个问题的答案不能只看性能因为单从吞吐量来看Plus和开源版在同样配置下没有天壤之别。真正的差异在三个地方。首先是主动健康检查。开源版默认只有被动健康检查也就是要等请求转发过去、发现连不上或超时才能把节点标记为失败。这意味着请求已经打到故障节点上产生了延迟用户可能已经感受到一次卡顿。Plus的主动健康检查会按你设定的时间间隔主动去探测后端节点的健康状态不等业务请求踩雷就能提前把它摘掉。其次是动态重新配置。开源版调整upstream里的节点时需要reload主进程reload那一瞬间虽然号称graceful但在极端高并发下还是会丢少量连接、内存峰值也会突然抬高。Plus支持通过API动态增删节点、调整权重完全不用重新加载配置这个能力在大促扩缩容时非常关键。第三是实时的活动监控。Plus自带一个状态页和API可以看到每个上游节点的连接数、响应时间、健康状态这些数据对线上调优和快速定位问题帮助极大。开源版虽然能通过Stub Status看到基础指标但远不如Plus的维度丰富。所以我的结论是如果只是内部小流量系统开源版够用但目标是百万级并发、需要常态化应急操作的场景Plus的主动健康检查、动态配置、监控能力能直接降低你的运维风险和人工干预成本。1.2 百万并发是什么概念先别急着立Flag在聊配置之前必须先掰清楚百万并发这个词。很多老板说的百万并发其实是每秒百万请求QPS而技术人员说的并发往往指同时在线连接数Concurrent Connections。这两者完全不是一个数量级。一个直观类比如果把每个请求当成一个人进商场QPS是每秒有多少人通过闸机并发连接数是当前时刻商场里一共有多少人。闸机吞吐量再高商场容量不够一样会堵人商场容量再大闸机太少单位时间进不来多少人。高并发架构这两个指标都要看但调整手段完全不一样。用实际数字说话单台经过调优的NGINX Plus在硬件充足、做七层反向代理的情况下处理几万甚至十万级并发连接是能做到的但如果目标是百万级同时在线连接或者数十万级QPS单机一定扛不住。这里面的瓶颈往往不在Nginx本身而在内核网络栈、文件句柄限制、网卡中断处理能力还有后端的真实处理能力。所以百万级并发在实操中一定需要一个前置条件合理的横向扩展架构。NGINX Plus在其中扮演的是最前排的七层流量调度员而不是单打独斗的超级英雄。这个认知如果不建立后面的调优方向就会走偏。1.3 整体架构设计思路多级负载各司其职我在这次项目中采用的架构是典型的四层入口 七层分发组合。最外层用LVSLinux Virtual Server或者云平台的四层负载均衡器负责承载海量TCP连接把流量分发给后端的NGINX Plus集群NGINX Plus集群再根据业务规则把请求转发给后端的应用服务池。这套架构的好处是每一层都做自己最擅长的事。四层负载不解析HTTP只做IP和端口级别的转发性能极高承载百万级TCP连接没有问题。NGINX Plus在这一层之下收到的已经是分散过的流量每一台的并发压力就能控制在合理范围内。再加上Keepalived做VIP漂移即使某一台NGINX Plus宕机整个入口也不中断。应用层如果已经容器化NGINX Plus的upstream配置可以结合服务发现动态更新如果还是传统虚拟机部署就用Plus的API做扩缩容。整体思路就是流量能早分发就早分发每一层的数据面尽量保持轻量把状态和复杂度往上推或者外置化。2. Ubuntu 20.04上的环境准备与NGINX Plus安装2.1 操作系统级别的预调优先把地基打好很多人一上来就改nginx.conf结果压测时发现并发连接数怎么都上不去最后查出是系统文件句柄受限这种本末倒置的排查路径实在太常见。在装NGINX Plus之前我建议先把Ubuntu 20.04的几个关键系统参数调整到位。第一个是文件句柄限制。Linux下一切皆文件一个TCP连接就是一个文件描述符。默认的ulimit是1024意味着进程最多打开1024个文件这对高并发场景来说连零头都不够。修改方式是编辑/etc/security/limits.conf或者对于systemd管理的服务直接在service文件中设置LimitNOFILE。NGINX Plus通过systemd启动时LimitNOFILEinfinity这个配置比在nginx.conf里写worker_rlimit_nofile更优先级高两个最好都设。第二个是TCP协议栈相关的内核参数。百万级连接意味着大量的TIME_WAIT和TIME_WAIT复用、连接追踪、端口范围都需要调整。常见的几个sysctl参数我在后面章节给出完整配置表。在安装之前先把这些参数写入/etc/sysctl.d/99-nginx-tuning.conf执行sysctl -p生效即可。第三个是网卡和中断绑定。如果服务器是物理机或者有SR-IOV能力的云主机建议确认多队列网卡已经把队列分配给多个CPU核心避免所有中断都打在CPU0上。Ubuntu 20.04下可以通过ethtool -l eth0查看队列数用irqbalance服务做自动均衡。这一步很多人忽略但压测时你会发现单核软中断100%是家常便饭。2.2 NGINX Plus安装流程走官方源是最省心的方式NGINX Plus不像开源版那样直接apt install nginx就能装它是商业订阅产品需要配置官方仓库并验证订阅证书。当然我这里不讨论付费和试用申请的细节只说安装技术路径。通常在官网完成订阅申请后NGINX会提供一份安装指引核心步骤是下载官方的nginx-plus-版本.repo文件放到/etc/apt/sources.list.d/同时配置对应的GPG Key。然后在Ubuntu 20.04上执行apt update。更新完成后直接apt install nginx-plus即可。安装完成后建议马上验证版本和编译参数nginx -v nginx -Vnginx -V输出非常重要它能告诉你当前版本默认编译了哪些模块。重点确认是否有--with-stream四层负载和TCP代理功能、--with-http_v2_moduleHTTP/2支持、--with-http_ssl_moduleSSL支持。Plus版一般都已包含但如果某些特殊模块缺失后面配置时就会出现unknown directive的报错。2.3 安装后的文件布局与基础配置骨架NGINX Plus在Ubuntu上的文件布局和开源版基本一致。主配置在/etc/nginx/nginx.conf子配置目录有/etc/nginx/conf.d/和/etc/nginx/sites-available/。我的习惯是直接使用conf.d目录把每个业务域名的配置拆成独立文件upstream配置单独放一个文件这样线上排查时一眼就能找准位置。基础骨架建议这样划分# /etc/nginx/nginx.conf user www-data; worker_processes auto; worker_rlimit_nofile 655350; events { worker_connections 65535; use epoll; multi_accept on; } http { # 这里include mime.types、gzip配置、log_format等 include /etc/nginx/conf.d/*.conf; }这里把worker_processes设为auto让Nginx自动按CPU核心数启动worker进程。worker_rlimit_nofile 655350保证每个worker进程能打开足够多的文件描述符。worker_connections 65535配合多worker理论上单机就能抗住几十万并发连接worker_processes * worker_connections是理论上限。3. NGINX Plus负载均衡配置与核心参数调优3.1 upstream服务池配置详解权重、连接数、慢启动一个都不能少NGINX Plus的负载均衡核心是upstream块。这里我给出一个生产环境可用的示例并逐个解释关键指令# /etc/nginx/conf.d/upstream.conf upstream backend_api { zone backend_api 64k; least_conn; server 10.0.1.11:8080 weight5 max_conns1024 slow_start30s; server 10.0.1.12:8080 weight5 max_conns1024 slow_start30s; server 10.0.1.13:8080 weight3 max_conns512 slow_start30s; keepalive 256; keepalive_requests 100000; keepalive_timeout 60s; }第一个要点是least_conn。默认的轮询round-robin在请求耗时不均匀的场景下容易把请求打给慢节点造成某个后端连接堆积。而least_conn会把新请求先交给当前活跃连接数最少的节点更适合高并发下后端处理能力存在波动的情况。第二个要点是max_conns。它限制单个NGINX Plus worker到某台上游的最大并发连接数防止某个后端节点被打爆。这里的值不是拍脑袋定的最好根据后端的压测基线来算比如后端单机能扛2000 QPS平均响应时间100ms那并发连接数大约就是2000 * 0.1 200。你在这里设定的max_conns要等于所有worker进程的连接数之和不能只看单个数值。第三个要点是slow_start。在节点刚恢复或者刚上线时慢启动会让Nginx逐步向该节点增加请求量避免冷节点瞬间被流量冲垮。这个在生产发布时非常实用特别是配合Plus的动态上下线API能做到真正的无损发布。zone backend_api 64k是NGINX Plus独有的配置它把upstream的状态放到共享内存中这样所有worker进程可以共享同一份节点健康状态并允许通过API动态修改。如果没有这行动态配置能力就用不了。3.2 关键性能参数调优这些数字后面都有计算逻辑很多文章会列一串调优参数但不说为什么是这个值这里我把几个最关键的参数背后的计算逻辑讲清楚。第一个是worker_processes。在纯反向代理场景下Nginx的worker是CPU密集型还是IO密集型取决于你开启了多少特性。如果开了SSL、gzipCPU消耗显著worker数量设为CPU核心数即可。但如果主要做纯转发、大量连接处于空闲等待可以适当增加worker但不要超过核心数的1.5倍否则上下文切换本身就成了瓶颈。实测下来32核的机器设autoNginx会启动32个worker效果通常就是最优的。第二个是worker_connections。它表示每个worker进程能同时打开的最大连接数。单机理论并发上限公式是worker_processes × worker_connections。但注意反向代理场景下一个请求要占用两个连接客户端到Nginx一个Nginx到后端一个所以实际能承载的并发请求数大约是理论值的一半。比如worker_processes 32、worker_connections 65535理论上限约200万减半后还有100万这就是很多人说单机百万并发的来源。但你这个100万是并发连接还是QPS如果是100万QPS那单机做不到如果是100万连接同时在线上面这些参数配合系统调优是有可能的。第三个是keepalive相关参数。这是很多人忽略但实际上影响巨大的点。keepalive 256表示每个worker进程与后端服务器之间保持的空闲keepalive连接数。如果这个值设置得太小Nginx每次发给后端都需要重新建TCP连接造成大量的TIME_WAIT并发一上来后端会被大量新建连接拖垮。keepalive_requests表示一条keepalive连接最多能复用的请求次数设得越大越好官方默认100生产建议设到10000以上减少周期性断连重连。keepalive_timeout设置空闲连接保持时间太长浪费后端资源太短会导致频繁重连60秒左右是比较平衡的选择。3.3 让连接更持久HTTP/2、SSL会话复用与客户端长连接在高并发场景下客户端与NGINX Plus之间的连接管理同样关键。我在这套架构里启用了HTTP/2它通过多路复用让一条TCP连接上可以并行传输多个请求极大减少了TCP握手和慢启动带来的延迟。server { listen 443 ssl http2; server_name api.example.com; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache shared:SSL:20m; ssl_session_timeout 30m; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; location / { proxy_pass http://backend_api; proxy_http_version 1.1; proxy_set_header Connection ; } }ssl_session_cache这一项容易被忽略但它在HTTPS场景下能省掉大量重复的TLS握手开销。20MB的共享缓存大约能存10万左右的会话ID对百万级连接来说可以明显降低握手造成的CPU消耗。客户端证书校验如果不需要就关掉每次握手都做完整握手的话性能下降几十个百分点点都很正常。proxy_set_header Connection 这一行是开启后端keepalive的必备条件。如果你还保留着默认的Connection: close头上面upstream里配的keepalive 256就白配了Nginx会每次都用新的连接请求后端。关于监听端口的优化如果业务允许建议在listen指令后加上reuseport参数。它允许多个worker各自监听同一个端口并由内核负载均衡分配新连接能显著减少worker之间的锁竞争。注意这个参数在部分旧版本内核上有坑Ubuntu 20.04默认内核5.4实测没问题。3.4 健康检查与会话保持Plus的两个杀手级功能前面提到主动健康检查是Plus相对开源版的核心优势这里给出一个具体的配置upstream backend_api { zone backend_api 64k; least_conn; server 10.0.1.11:8080 max_fails0; health_check interval5s fails2 passes3 timeout2s uri/healthz; health_check_timeout 5s; }这个配置让NGINX Plus每隔5秒主动向后端节点的/healthz接口发起一次HTTP请求连续失败2次标记为不健康连续成功3次恢复上线。相比开源版的被动检查这个机制在流量高峰时不需要先把请求转发给故障节点才察觉问题用户体验的稳定性会明显好很多。会话保持Sticky Session在高并发下有个很实际的用途当一个用户连续多个请求需要落在同一台上游服务器时最典型的例子是短时缓存不共享的场景。Plus支持三种粘滞方式sticky cookie、sticky learn和sticky route。upstream backend_api { zone backend_api 64k; sticky cookie srv_id expires1h; server 10.0.1.11:8080; server 10.0.1.12:8080; }sticky cookie方式会在客户端种一个Cookie后续请求根据Cookie里的路由信息分发到对应节点实现简单且对后端透明。需要注意它的副作用有状态会话落到某台节点后如果该节点故障需重新负载可能导致会话丢失或短暂报错。在百万级并发这种体量下我通常建议尽量把业务做成无状态的把Sticky Session作为最后的兜底方案。4. 性能压测与并发能力验证别拍脑袋说能扛百万4.1 压测工具选择wrk、ab、JMeter到底用哪个做高并发压测时很多人第一反应是abApacheBench。ab简单但问题很明显它是单线程模型压到一定并发后客户端自身先成为瓶颈而且生成的实际并发请求能力有限。我实测过ab在30000左右的并发下就很不稳定了数据波动很大。更推荐的是wrk它能利用多核CPU和多线程单台压测机就能打出几十万级别的连接和请求。核心用法如下wrk -t 8 -c 20000 -d 60s --latency http://10.0.0.1/-t 8表示开8个线程-c 20000表示总共保持2万个并发连接-d 60s表示压测60秒--latency输出延迟分布。注意-c指定的是并发连接数不是总请求数wrk会在每个线程内维持这些连接持续发请求。如果你的测试场景包含登录、下单、查询等多个接口混合或者需要设置Header、POST请求体wrk的lua脚本也能满足。不过更接近真实业务的做法是用JMeter它支持分布式压测、复杂场景编排、断言和聚合报告。对NGINX Plus这种七层负载均衡验证JMeter更适合模拟多用户多场景的复杂业务链对纯验证Nginx本身能扛多大压力wrk更轻量、更直接。4.2 压测参数设计与并发数确认思路jmeter压测怎么确认系统的并发数这个热搜问题其实有一个基本套路不是压完之后直接看一个报告的并发数就完事而是要通过逐步加压找到拐点。我的做法是阶梯式加压。先从低并发起步比如1000并发跑5分钟记录QPS、P99延迟和错误率然后逐步增加到5000、10000、20000每档跑完都记录数据。观察趋势时你会看到某个并发拐点之后QPS不再继续上涨甚至下跌P99延迟突然陡增说明系统已经接近或进入过载状态。这个拐点对应的并发和QPS才是你有依据的核心指标。压测时还要分清两个数据Requests/sec和Connections。Requests/sec是QPSConnections是同时在线连接数。如果老板问系统能扛多少并发你至少要能说出这两个维度各自的数据而不能只说一个模糊的数。实测数据举例在我最近一次项目中NGINX Plus所在节点是32核64GB内存worker_processes autoworker_connections 65535开启HTTP/2和SSL后端服务接口平均响应时间50ms。用wrk从压测机打出50000并发连接时Nginx端QPS稳定在16万左右P99延迟从5%开始略有上翘但整体平稳。继续加到80000并发P99延迟大幅上升说明虽然Nginx还能维持连接但配合后端后整体链路已经到极限了。这个数据反过来也能作为后端扩容和架构优化的依据。4.3 从压测结果反向排查瓶颈压测数据出来了但QPS不符合预期怎么定位瓶颈我是按下面这个顺序排查的。先看CPU。通过top观察Nginx的worker进程CPU占用率如果某个worker打满100%而其他worker空闲多半是worker之间负载不均衡可能和worker数量、accept_mutex开关、网卡多队列配置有关。如果所有worker都打到80%以上说明是CPU瓶颈需要加机器或者减少SSL、gzip这类CPU密集操作。再看内存和文件句柄。用free -h看内存是否吃紧用cat /proc/net/sockstat看TCP连接状态分布。如果TIME_WAIT数量巨大说明短连接过多这时候应该检查前后端keepalive是否生效而不是急着调大端口范围。然后看网卡。vmstat里如果有大量si/soswap in/out或者top里softirq软中断占比高网卡或驱动可能成为瓶颈。这是在压测百万级并发时最常见的现象——CPU还没打满网卡先把CPU打满了因为百万级连接的收包和发包会产生大量软中断。最后才是看Nginx日志和Plus监控API。Plus的/api/5/nginx/接口能实时吐出一堆数据包括当前活跃连接数、每台上游的连接数与响应时间、各worker的请求计数这些数据对定位瓶颈非常有帮助。4.4 压测过程中的几个真实坑压测这个环节踩过的坑真的不少挑几个典型的说说。第一个坑压测机自己先崩了。wrk在高并发下如果线程数和连接数设置得太大压测机本身的内核参数和文件句柄也需要调优。我遇到过几次压测机网卡中断全部打在一个核上导致数据不准确。所以压测之前压测机的ulimit、TCP端口范围最好也跟着调一下。第二个坑TIME_WAIT爆炸导致端口无法复用。如果压的是TCP短连接客户端没有启用keepalive压测机在和Nginx建连后再断开会产生大量TIME_WAIT。默认的net.ipv4.ip_local_port_range只有28000多个端口压测并发超过这个数新连接就被拒绝了。调大端口范围为1024 65535同时开启net.ipv4.tcp_tw_reuse能有所缓解。第三个坑把Pinpoint、APM监控代理装在NGINX Plus同一台机器上压测。有些APM Agent会以Sidecar方式共享主机端口或占用CPU压测结果和预定值差一大截。压测时尽量保证数据面干净监控采集靠旁路流量镜像或走Plus自带的metric API。5. 百万级并发的进阶调优从内核到架构逐层啃5.1 内核网络栈深度调优一整套可直接抄的sysctl配置下面这套sysctl配置是我在多个百万级连接项目中反复验证过的基线直接保存到/etc/sysctl.d/99-ngx-plus-highconcurrency.conf然后执行sysctl -p即可# 连接跟踪表加大百万连接时默认65536肯定不够 net.netfilter.nf_conntrack_max 1048576 # TIME_WAIT复用与回收 net.ipv4.tcp_tw_reuse 1 # 本地端口范围尽量放开 net.ipv4.ip_local_port_range 10240 65535 # TCP读写缓冲区加大 net.ipv4.tcp_rmem 4096 87380 16777216 net.ipv4.tcp_wmem 4096 65536 16777216 # 最大积压连接数 net.core.somaxconn 65535 net.ipv4.tcp_max_syn_backlog 65535 # 提升文件句柄上限 fs.file-max 2097152 fs.nr_open 2097152 # 关闭IPv6如果不用 net.ipv6.conf.all.disable_ipv6 1 net.ipv6.conf.default.disable_ipv6 1这里有几点需要特别说明。net.ipv4.tcp_tw_reuse只对主动发起连接的一方也就是客户端视角有效它允许内核复用处于TIME_WAIT状态的连接用于新的出站连接能显著缓解高并发短连接下的端口耗尽问题。千万别开tcp_tw_recycle这个参数在NAT环境下会引发严重的安全问题和随机丢包Ubuntu 20.04默认也把它移除了。nf_conntrack_max只在加载了nf_conntrack模块时有意义。如果Nginx所在节点没有跑iptables的NAT规则其实可以完全不再加载连接跟踪模块毕竟连接跟踪本身就吃资源。检查一下lsmod | grep conntrack如果确认不用可以用modprobe -r把它卸载或者干脆不加载性能还能再往上升一点。5.2 多级负载架构与Keepalived高可用前文说过单台Nginx扛不住百万级并发需要多级架构。在实际项目中我在四层入口层用了LVS做DR模式的负载均衡LVS后面挂两台NGINX Plus作为七层分发集群再用Keepalived在这两台NGINX Plus之间做VIP漂移。具体来说LVS层只是把目标IP和端口做改写不解析HTTP。它能承载极大的流量因为它的转发路径短、不做任何业务逻辑。LVS本身也要做高可用通常用主备模式配合Keepalived漂移VIP。NGINX Plus层同理两台机器共用同一个VIP一台宕机或者主动维护时VIP自动漂移到另一台整个入口不中断。这套架构在扩展上很灵活当流量涨上来最简单的方式是在LVS下扩容NGINX Plus节点新节点挂到同一组Keepalived实例里不影响VIP主备关系如果后端进一步吃紧就在NGINX Plus的upstream里动态加后端节点。Plus的API在这里就体现出了优势——完全不用动nginx.conf直接调API就会生效。# 示例通过Plus API动态添加后端节点 curl -X POST http://127.0.0.1/API/5/stream/upstreams/backend_api/servers/ \ -H Content-Type: application/json \ -d {server:10.0.2.21:8080,weight:5,max_conns:1024}5.3 限流、熔断与流量治理高并发下的减震器当一个人面对百万级并发如果后端资源跟不上最怕的不是流量大而是流量一拥而上来不及处理导致全链路雪崩。NGINX Plus自带限流能力可以充当流量治理的减震器。最基本的限流是limit_req它控制的是请求速率单位时间内的请求数limit_req_zone $binary_remote_addr zoneapi_limit:10m rate100r/s; server { location /api/ { limit_req zoneapi_limit burst200 nodelay; proxy_pass http://backend_api; } }这段配置的含义是每个客户端IP每秒最多100个请求burst200允许瞬时突发200个请求排队nodelay表示突发部分不延迟消费而是立即转发给后端前提是后端还能承受。这个参数必须根据后端真实吞吐能力来定后端压测QPS如果是2000后端有5台那么rate可以设到五六千的级别让NGINX Plus只是一个整流器而不是过度限流的闸门。除了请求限流还有limit_conn做连接数限制防止某个客户端占用大量连接导致其他用户无法访问。这两种限流组合使用能让系统在大促或者被恶意刷流量时保持稳定的响应质量。熔断在NGINX Plus的运维层面上主要体现在健康检查和max_fails配合上。当Plus的主动健康检查发现某台后端连续失败达到阈值后会把它从upstream里摘除流量自动转向健康节点这其实就是一种熔断。如果你的后端是微服务架构通常还会在更上层搭配Sentinel这类流量治理组件做服务级别的熔断和降级NGINX Plus负责网关入口层的保护两套体系各司其职。5.4 与微服务和容器化环境的联动当前很多业务已经把后端容器化部署在K8s里NGINX Plus在容器化环境下的定位通常会变成Ingress Controller或者边缘流量网关。一个常见的疑问是K8s的Service本身也有负载均衡能力为什么还要专门用NGINX Plus答案在于控制力和可观测性。K8s Service的负载均衡是进程内转发虽然简单但很难做精细化流量策略比如按请求Header做灰度分流、按客户端IP做限流、A/B测试、自定义健康检查路径。NGINX Plus在这里可以基于Ingress Controller的方式运行也可以在NodePort前面提供统一的入口管理。如果你已经用了Plus的License完全可以在容器化环境中把同样的逻辑平移过去upstream改从服务发现动态获取Pod IP健康检查继续用Plus的主动探测Session保持和限流策略全部保留。多说一句在这一层做调优时不要忘记JVM层面如果后端是Java服务类似JVM参数调优堆大小、GC策略选择会影响后端响应时延而NGINX Plus的keepalive、超时参数也要与后端的处理时延匹配。比如后端要求连接不能闲置太久那么Nginx的upstream keepalive_timeout就要比后端的socket超时短避免出现PS连接被后端关闭的报错。6. 常见问题与排查技巧实录6.1 压测时并发数上不去先查这几项一个问题我wrk都设到-c 50000了为什么Nginx日志里的活跃连接数停留在几千这种情况十有八九不是Nginx的问题而是链路中某个环节的隐性瓶颈。按照我自己的排查顺序先看系统监控top和vmstat确认CPU和内存没有被打满再看/proc/net/sockstat确认TCP: inuse的分配情况然后看Nginx的error.log里有没有worker_connections are not enough的报错。如果出现这个报错说明worker_connections设置的数值低于实际需要的并发连接数把这个值和worker_processes的乘积调高即可。还有一个容易被忽略的wrk压测时如果压的是HTTPSTLS握手本身会成为初始瓶颈。即使最终能承载高并发但要先确认SSL session cache是否生效。在压测的刚开始阶段你可能会看到CPU的使用率飙升那是因为每个新连接都在做完整TLS握手。开了ssl_session_cache后这个现象会明显缓解。6.2 后端负载不均时的排查套路NGINX Plus的least_conn算法理论上应该让负载均衡得很均匀但实践中经常看到某台后端的连接数远超其他节点。原因通常有三类一是max_conns设置差异导致某些节点被优先分配二是健康检查状态不一致某个节点被Plus标记为不健康后流量全部转移到其他节点三是某种业务场景下请求的响应时间差异太大比如连了慢SQL的节点QPS低反而容易积累连接。排查时先通过Plus的/api接口查看每台上游节点的活动连接数、请求数和响应时间分布再用curl逐台测试后端的真实响应速度。如果确认某台后端处理慢优先查它自身的资源和依赖而不是怀疑Nginx配置。6.3 HTTP 502/504报错排查高并发压测时不时会出现502或504这两个状态码含义不同排查方向也不同。502 Bad Gateway表示NGINX Plus无法从后端获得有效响应常见原因包括后端服务崩溃没起来、Keepalive连接被后端提前关闭、后端返回了非法的HTTP响应格式。504 Gateway Timeout表示后端在规定时间内没有响应完成proxy_read_timeout默认是60秒如果你的后端有长任务逻辑需要显式调大这个值。这里有一个特别典型的场景开启了后端keepalive后反而频繁出现502。原因是后端服务尤其某些Java应用的空闲连接回收策略与Nginx的keepalive不匹配连接被后端断开后Nginx毫不知情仍继续使用结果请求一发出就收到RST。这种问题一般有两种解法一是缩短Nginx的keepalive_timeout让Nginx更早回收空闲连接二是后端也开启TCP keepalive机制让双方连接的超时时间尽量匹配。# 查看当前建立的tcp连接状态排查是否存在大量连接处于异常状态 ss -ant | awk {print $1} | sort | uniq -c | sort -rn # 查看端口监听情况 ss -lntp | grep -E :(80|443) # 实时查看Nginx访问日志中5xx状态码 tail -f /var/log/nginx/access.log | awk $9 ~ /^5[0-9][0-9]$/ {print $0}6.4 从Plus监控API定位慢请求NGINX Plus自带的活动监控API在排查慢请求时非常好用。通过下面这个请求可以拿到当前Nginx所有关键指标curl -s http://127.0.0.1/API/5/nginx/ | jq返回的数据里重点关注requests.total、requests.current、connections.active、connections.waiting这几个字段。waiting表示处于空闲keepalive状态的连接数如果这个值非常小说明客户端连接大多处于活跃状态但吞吐量上不去问题可能在后端如果waiting巨大而active很小说明客户端连接大量空闲这个时候要检查前端是否有连接池泄漏或客户端连接没有正常复用。针对每个upstream节点还可以查看/api/5/http/upstreams/backend_api/下的节点级数据包括requests、responses、health_checks的失败次数以及busy连接数。busy连接数持续偏高是后端处理能力跟不上最直接的一个信号这时候就算Nginx配置再优化也解决不了根本问题该扩容后端了。7. 最后再分享一点经验这套配置和调优流程我在多个项目里验证过得到的结论是百万并发绝对不是一个单纯改配置就能做到的事情它需要系统层、配置层、架构层三者一起配合。如果你跑在小流量环境不需要一上来就追求极限参数先按照这篇文章的步骤把系统参数和基础配置调到合理水平让NGINX Plus平稳运行再逐步压测验证才是最务实的方式。还有一点个人的体会NGINX Plus的调优不要教条化。很多人拿着网上的最佳实践直接套用却忽略了业务模型的不同。比如你的业务是小报文、高QPS那需要重点调网络缓冲区和事件处理如果你的业务是大响应体、低并发那就要偏重调整proxy_buffering和后端连接复用。参数不是越多越极端越好真正有效的调优必须建立在业务流量特征和实测数据之上。这大概也是我在一次次压测和救火中收获最多的一件事。
返回列表