尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Ingress Nginx 高性能调优:从内核参数到 10 万 QPS 的完整实践
1. 为什么你的 Ingress Nginx 跑不到 10 万 QPS先把话说在前面Ingress Nginx 单机 10 万 QPS这个目标不是玄学但也绝不是把worker_processes改成auto、把内存调大就能碰到的。我原先帮某电商中台调过一版 Nginx Ingress业务高峰期集群内三四副本单副本撑死两万左右 QPS还经常出现 upstream timeout 和连接重置。后来逐步把内核栈、TLS、upstream 连接池、worker 模型全都过了一遍单副本稳定跑到 9 万到 10 万 QPSP99 延迟控制在 50ms 以内纯静态回源场景我才敢说这条路是通的。很多人对性能调优有个误解觉得瓶颈一定在 Nginx 本身。实际上在高并发场景下最先扛不住的是操作系统网络栈其次是 TLS 握手计算再往后才是 Nginx 的 worker 模型和日志落盘。也就是说你拿着默认配置的 Nginx Ingress 去压测经常看到的现象是Nginx 的 CPU 占用率没满但 QPS 已经上不去了或者干脆出现大量 connect timeout。这个时候问题多半出在系统层——半连接队列、TIME_WAIT、本地端口耗尽、软中断不均每一项都能把你的 QPS 压死在一个看似很低的数字上。这篇文章面对的是已经能跑通 Kubernetes Nginx Ingress、但想进一步压榨性能的开发和运维同学。我会按照我的调优顺序来写先估量目标再做内核参数再调 Ingress 自身的 worker、keepalive、TLS 和日志最后给完整的压测方法和排障路径。每一条配置我都会说清楚为什么这么改以及改完以后你期望看到什么效果方便你照着落地也方便你判断哪些配置在你的场景下不该盲目照抄。2. 先算一笔账10 万 QPS 背后到底需要什么2.1 你可以先估算请求模型10 万 QPS 听起来很吓人但拆开算就清晰了。如果平均每个请求体 1KB、响应体 2KB那么每秒经过的数据量大概是请求方向 100MB/s响应方向 200MB/s总吞吐约 300MB/s。这个量级对万兆网卡来说游刃有余但假如你的响应体是 20KB、50KB那吞吐会直接飙到 GB 级瓶颈就从 Nginx 变成网卡和内存带宽了。所以我问你一句你要扛的 10 万 QPS是纯小包转发还是大 Body 业务另外一个关键量是连接模型。10 万 QPS 如果全部走短连接意味着每秒要新建 10 万次 TCP 连接每次连接握手都要经过内核协议栈还会产生大量 TIME_WAIT 状态连接这对任何机器都是巨大的负担。真正能单机跑到这个量级的生产场景几乎都是靠 keepalive 长连接复用的客户端到 Ingress 保持长连接Ingress 到后端也保持长连接QPS 高但连接新建速率低系统的压力会小一个量级。所以在调优之前你先要明确自己的场景我帮你列一个检查表平均请求体多大平均响应体多大客户端是浏览器、App 还是服务端 API业务允许 keepalive 吗客户端有没有连接池是 HTTPS 还是 HTTP证书链有多长后端应用支持 HTTP 长连接吗请求是打到静态缓存、内存数据还是每次都要查数据库这几项不需要全部满足但每一项都会直接决定你的瓶颈重心。比如客户端如果是服务端 API 调用那连接池和 keepalive 基本可控如果是浏览器海量短连接那你要重点处理 TIME_WAIT 和 TLS 握手开销。2.2 性能瓶颈到底在哪一层根据我自己调过的集群按出现频率排瓶颈大概是这样的顺序第一梯队内核网络参数。半连接队列溢出、TIME_WAIT 积压、本地端口耗尽这些是系统级硬限制Nginx 配置再好也突破不了。第二梯队TLS 握手。ECDHE 密钥交换和 RSA 签名验证都是 CPU 密集操作突发流量进来时CPU 会瞬间被打到满但 Nginx 的 worker 明明没干多少活。第三梯队Nginx 自身的连接模型。worker 数量、连接数上限、事件处理方式、accept 行为这些决定高并发下能否把 CPU 用满。第四梯队upstream 连接池。Ingress 到后端如果每次新建连接后端应用和 Nginx 都会背上巨大的连接管理成本。第五梯队日志、监控、网络插件等其他因素。最容易被忽略但往往最后成为压死骆驼的最后一根稻草。记住这个优先级你调优的时候就会有条理不会东一榔头西一棒子。3. 内核参数是性能的地基必须最先调3.1 为什么你的默认内核参数撑不住高并发Linux 默认的内核网络参数本身就不是为了单机 10 万 QPS 设计的。默认的net.core.somaxconn是 128很多发行版是 4096 或 4096 以上但依然不够半连接队列tcp_max_syn_backlog是 1024本地端口范围是 32768-60999TIME_WAIT 要等 60 秒。这些默认值放在桌面环境或普通服务器上没问题但一旦进入每秒上万请求的节奏立刻就会露出短板。我举个实际例子某次压测目标 QPS 3 万短连接模型我明显看到客户端报 connect timeout但服务端 CPU 利用率还不到 50%。用ss -lnt一看监听队列的 Recv-Q 积压了几百说明新连接已经排队到了用户态之外而 Nginx 还来不及 accept。这就是 somaxconn backlog 不够的直接表现。3.2 一套可以直接用的 sysctl 配置下面这组参数是我多个项目里验证过、可以覆盖绝大多数高并发场景的基线配置。你直接放到/etc/sysctl.d/99-ingress-tuning.conf然后执行sysctl -p /etc/sysctl.d/99-ingress-tuning.conf生效即可。# 监听队列与半连接队列 net.core.somaxconn 65535 net.core.netdev_max_backlog 65535 net.ipv4.tcp_max_syn_backlog 65535 # 本地端口范围 net.ipv4.ip_local_port_range 1024 65535 # TIME_WAIT 优化 net.ipv4.tcp_fin_timeout 15 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_max_tw_buckets 200000 # TCP 读写缓冲区 net.ipv4.tcp_rmem 4096 87380 16777216 net.ipv4.tcp_wmem 4096 65536 16777216 net.core.rmem_max 16777216 net.core.wmem_max 16777216 # 全连接队列溢出时直接丢弃而不是发 RST net.ipv4.tcp_abort_on_overflow 0 # 文件句柄上限 fs.file-max 2000000逐条解释一下关键项net.core.somaxconn全连接队列长度也就是 accept 队列。Nginx 的listenbacklog 参数会和这个值取 min所以两边的数值都要调大。如果队列满了内核会丢包客户端表现为连接超时或重置。net.ipv4.tcp_max_syn_backlog半连接队列长度保存还没完成三次握手的连接。攻击或者瞬时突刺流量来了这个队列很容易被打满。net.ipv4.ip_local_port_range这个是给 Nginx 向后端转发时用的。Nginx 作为客户端连接 upstream 时内核会分配本地端口默认只有 3 万多个如果大量短连接端口很快耗尽你会看到 connect 失败或 EADDRNOTAVAIL。net.ipv4.tcp_tw_reuse允许内核复用 TIME_WAIT 状态的连接。注意这个只对主动发起连接的方向有效也就是 Nginx 转发到后端时有用对入站连接无效。客户端侧的 TIME_WAIT该等还是得等。net.ipv4.tcp_fin_timeout把 TIME_WAIT 的等待时间从 60 秒缩到 15 秒缓解端口压力。提醒一下不要再去配tcp_tw_recycle它在 NAT 环境下会产生严重的连接异常问题新内核已经移除了这个参数。网上很多老文章还把它当宝照着抄就是在给自己埋坑。3.3 文件句柄和进程限制别漏了Nginx 单进程需要大量文件描述符。默认的ulimit -n是 1024这在高并发下连热身都不够。调度系统层面在 Kubernetes 里你还要检查节点上的 systemd 参数。我通常会在节点上确认ulimit -n cat /proc/sys/fs/file-max然后把 Nginx worker 使用的worker_rlimit_nofile调大这个值要大于worker_connections乘以 worker 数。比如 8 个 worker每个 worker 2 万连接那worker_rlimit_nofile至少要设成 200000。否则连接还没打满Nginx 先报 too many open files。4. Ingress Nginx 配置调优每一个参数都有它的道理4.1 worker 数量与连接数上限Ingress Nginx 的 worker 模型和原生 Nginx 一样都是事件驱动、单进程多连接。但具体配置项需要通过 ConfigMap、Annotation 或者挂载配置模板来覆盖。这里我要先纠正一个认知worker_processes auto不等于最优。auto会自动检测 CPU 核数但在容器环境下它会读取到宿主机的 CPU 数量而不是容器 limit 里指定的 CPU 数量。这会导致 worker 数过多、线程切换成本上升或者 worker 数过少、CPU 用不满。我建议在 ConfigMap 里显式配置worker-processes数值和你在 Deployment 里设置的 CPU limit 保持一致。比如你给 Ingress 容器分配了 8 核 CPU limit那就配置成 8 个 worker。对应的连接数参数是worker-connections它决定了每个 worker 可以同时维持的最大连接数。计算公式是最大连接数 ≈ worker_processes × worker_connections。想要支撑 10 万 QPS如果 keepalive 复用做得好并发连接数可能只有几千到一万但如果短连接居多连接数会非常高。按 8 个 worker 来算worker-connections至少要 20000 才能给并发连接留出足够空间。4.2 客户端 keepalive让 HTTP 连接活得更久客户端到 Ingress 的连接复用在 Ingress Nginx 的 ConfigMap 里体现为三个参数keep-alive: 1024 keep-alive-requests: 10000 keep-alive-timeout: 60skeep-alive控制每个 worker 能保持的空闲 keepalive 连接数上限。这个数值要够大否则高并发下连接经常被踢掉重建。官方默认值比较保守我通常直接调到 1024。keep-alive-requests单个 keepalive 连接上最多能处理的请求数。默认 100这在实际生产中太低了。一旦达到上限Nginx 会主动关闭连接客户端需要重新建连。压测时如果这个值小你会看到大量的重建连接QPS 上不去CPU 却飙高。我建议调到 10000。keep-alive-timeout空闲连接的存活时间。太短会导致频繁断开太长会占用连接资源。60 秒是我常用的基线值但如果你客户端数量巨大、连接资源紧张可以适当调到 30 秒。这里要特别注意客户端侧的 keepalive 是双向的光 Nginx 这边支持没用客户端也要真的复用连接。如果你用 wrk 压测wrk 默认就支持连接复用如果你用 curl 写循环去压那就是一请求一连接结果会严重失真。4.3 upstream keepalive被忽略的最大性能杀手很多人以为 keepalive 只对客户端侧有意义其实 Ingress 到后端的连接复用才是提升 QPS 的关键。默认情况下Nginx Ingress 转发的 upstream 连接是短连接每个请求都会向后端新建 TCP 连接。在高 QPS 下这意味着后端的连接建立和销毁变得极其频繁不仅浪费 Nginx 的本地端口还会打爆后端的文件句柄和线程池。Ingress Nginx 在 ConfigMap 中有对应的 upstream keepalive 配置upstream-keepalive-connections: 1024 upstream-keepalive-requests: 10000 upstream-keepalive-timeout: 60这些参数对应 Nginx upstream 配置里的keepalive 1024;、keepalive_requests 10000;和keepalive_timeout 60s;。光调大连接数还不够。默认生成的 upstream 配置里如果缺少proxy_http_version 1.1和proxy_set_header Connection upstream keepalive 是不生效的。在 Ingress Nginx 里这两项默认是写进模板的但有些自定义模板或旧版本不一定有。你可以进入 Pod 里查看生成的 nginx.conf 来验证kubectl exec -it ingress-nginx-controller-xxxx -n ingress-nginx -- cat /etc/nginx/nginx.conf | grep -A 10 upstream upstream-default-backend如果看到keepalive 1024;、keepalive_requests 10000;、keepalive_timeout 60s;以及proxy_http_version 1.1那说明配置生效了。如果没有你就需要检查 ConfigMap 是否被正确挂载。4.4 TLS 握手CPU 的主要消耗点之一如果你的业务是 HTTPS10 万 QPS 的场景下TLS 握手的开销绝对不能忽略。每秒钟如果有几千个新连接需要做 TLS 握手CPU 的直接消耗会非常明显。优化 TLS 性能主要从这几点入手第一开启 SSL session cache。Nginx 的 session cache 可以复用 TLS 会话参数减少握手次数。在 Ingress Nginx 的 ConfigMap 里ssl-session-cache: true ssl-session-cache-size: 10m ssl-session-tickets: truessl_session_cache shared:SSL:10m大约可以存储 4000 个 session如果你的并发连接数远大于这个值可以加大到 20m 或 50m。ssl_session_tickets也要开启它可以让会话凭证在多个 worker 之间共享避免每个 worker 各自维护一份 cache。第二关闭老旧的协议和弱密码套件。ConfigMap 中的ssl-protocols建议设置为TLSv1.2 TLSv1.3然后通过ssl-ciphers配置高性能的加密算法组合优先使用 ECDHE AES-GCM 和 CHACHA20ssl-protocols: TLSv1.2 TLSv1.3 ssl-ciphers: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 ssl-prefer-server-ciphers: true第三开启 OCSP stapling。它可以由 Nginx 提前缓存证书链的 OCSP 响应终端客户端就不用再去证书颁发机构验证吊销状态省掉一次额外的网络往返。证书链比较大的时候这个优化尤其明显enable-ocsp: true你还要注意一点TLS 握手的 CPU 消耗大头在 ECDHE 密钥交换和证书签名验证上。这是 CPU 的实打实计算就算配置全部到位单核每秒能完成的握手数量仍然有限。因此建议给 TLS 密集的业务单独预留足够的 CPU必要时考虑在负载均衡层终结 TLS 或者升级硬件。4.5 HTTP 层优化gzip、缓冲和超时gzip-level: 压缩级别不要超过 3。等级越高CPU 消耗越大但压缩率的提升越来越小。级别 1 对 CPU 最友好压缩率也能接受。对纯文本 JSON API 场景这个收益非常明显。proxy-buffer-size: 默认 4k如果后端响应头特别大会导致 Nginx 缓冲区频繁扩展把它调到 8k 可以减少内存拷贝。proxy-buffering: 默认开启建议保持。它能让 Nginx 先把后端响应缓冲一部分再发给客户端避免高并发时把后端的速度压力直接传导到客户端连接上。client-header-timeout: 默认 60 秒在高并发下太长了。如果客户端迟迟不发完整请求这个连接会一直挂着占用资源。建议设置为 10 秒左右。client-body-timeout: 同理读取请求体的超时时间默认 60 秒建议调低。4.6 日志落盘隐形性能瓶颈很少有人第一时间想到日志。默认情况下Ingress Nginx 每个请求都会写一条 access log高 QPS 场景下这意味着一秒钟要往磁盘写 10 万条日志。哪怕你只是同步写一行磁盘 IO 也会成为瓶颈而且日志轮转、采集器消费也会带来额外的 CPU 和内存开销。我的处理方式有两种按需选择如果日志只用来审计不在线排查那就直接关闭 access logenable-access-log: false如果业务强制要求保留日志那就开启日志缓冲。Nginx access log 支持 buffer 参数把日志先写进内存缓冲攒到一定量再落盘。Ingress Nginx 的 ConfigMap 里可以通过access-log-params传递自定义参数例如buffer32k flush5s这样每秒落盘次数会大幅降低。另外server-tokens建议设为false一是避免泄露版本信息二是响应头里少了一个字段省一点点带宽属于蚊子肉但总比没有强。5. 一份可以直接抄作业的配置清单5.1 Ingress Nginx ConfigMap 完整示例下面这份 ConfigMap 是我在多个压测环境里验证过的基线配置你可以直接参考但要根据实际压测结果微调。apiVersion: v1 kind: ConfigMap metadata: name: ingress-nginx-controller namespace: ingress-nginx data: # worker 与连接数 worker-processes: 8 worker-connections: 20000 worker-rlimit-nofile: 200000 # 客户端 keepalive keep-alive: 1024 keep-alive-requests: 10000 keep-alive-timeout: 60s # upstream keepalive upstream-keepalive-connections: 1024 upstream-keepalive-requests: 10000 upstream-keepalive-timeout: 60 # TLS ssl-protocols: TLSv1.2 TLSv1.3 ssl-ciphers: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 ssl-session-cache: true ssl-session-cache-size: 10m ssl-session-tickets: true enable-ocsp: true # HTTP 优化 gzip-level: 1 proxy-buffer-size: 8k proxy-buffering: on client-header-timeout: 10 client-body-timeout: 10 # 日志与信息隐藏 enable-access-log: false server-tokens: false注意不同版本的 Ingress Nginx 对 ConfigMap 中 key 的名称会有差异。比如enable-access-log在某些版本里叫disable-access-log语义相反。应用配置之前先查一下当前版本对应的文档或者在 Pod 里实际查看生成的 nginx.conf 来确认效果。5.2 Deployment 资源分配与节点选择ConfigMap 之外Deployment 的资源分配同样重要。我建议给 Ingress Controller 预留独占的 CPU避免和其他高负载 Pod 争抢。resources: requests: cpu: 8 memory: 8Gi limits: cpu: 8 memory: 8Gi如果条件允许用 nodeSelector 把 Ingress 固定到高主频、高网卡性能的节点上然后配合节点亲和性确保节点上只跑系统组件和 Ingress不让别的业务 Pod 抢占 CPU。关于副本数我要说一个反直觉的结论如果你的目标是单机 10 万 QPS那么在性能调通之前副本数越少越好。副本多了压力被分散到多台机器单机瓶颈反而更难暴露。先把单副本调到能扛住 10 万 QPS再考虑扩展到多副本做 HA 和横向扩容。当多个副本同时工作时你要关注 LoadBalancer 层的连接调度策略尽量保持长连接和固定源 IP 的一致性否则后端应用会频繁看到连接跳变。5.3 验证配置是否生效改完 ConfigMap 后Ingress Controller 会自动 reload但我不建议直接信它。进去看一眼实际生成的配置是最稳妥的kubectl rollout restart deployment/ingress-nginx-controller -n ingress-nginx kubectl exec -it deployment/ingress-nginx-controller -n ingress-nginx -- cat /etc/nginx/nginx.conf | grep -E keepalive|worker_processes|worker_connections|ssl_session_cache重点核对这么几个值worker_processes、worker_connections、keepalive 相关配置、ssl_session_cache 的大小。只要这些和你 ConfigMap 里写的一致再开始压测不然你就是在调一个和自己预期完全不同的配置。6. 压测方法没有基线数据一切调整都是无头苍蝇6.1 选择压测工具和测试路径压测工具我用得最多的是 wrk简单直接还可以通过 wrk2 控制固定 QPS。但 wrk 更适合压测 Nginx 的并发上限因为它的模型是固定线程数和连接数然后尽可能多地发请求。如果你的目标是“打满 10 万 QPS 并保持稳定”那 wrk 的压法可能不够精准这时候用 wrk2 指定 QPS 更好。关键是测试路径。很多人的压测路径是压测机 - 云负载均衡 - Ingress Controller - 后端服务。这条链路上每一跳都会引入额外的变量当你发现 QPS 上不去很难判断是 Ingress 的问题还是负载均衡或后端的问题。我的做法是分两段测第一段压测机直接打到 Ingress Controller 的 NodePort不经过外部负载均衡验证 Ingress 自身的极限。第二段加上负载均衡验证全链路的极限。如果负载均衡本身有性能上限或者连接调度问题至少要能定位到它。避免从 Ingress 节点上自己发起压测因为本地回环路径不走网卡加上压测工具会占用本机 CPU结果参考意义很有限。6.2 压测指令与关键指标我用 wrk 压测的常用命令是wrk -t16 -c1000 -d60s --latency https://ingress-node.example.com-t1616 个线程-c10001000 个并发连接-d60s压测 60 秒--latency输出延迟分布这个参数组合适合做上限探测。但如果你要压到 10 万 QPS需要不断调大-c和-t直到 QPS 不再增长或者 P99 延迟开始恶化。同时要观察 Nginx 机器的状态CPU 使用率用户态高说明在跑业务逻辑内核态高说明网络栈压力大。软中断分布cat /proc/softirqs或者top按 CPU 看如果软中断集中在少数几个核上说明网卡队列和 RPS 配置有问题。连接状态ss -s看连接总数ss -tan state time-wait看 TIME_WAIT 数量。监听队列ss -lnt看 Recv-Q 是否积压。6.3 metrics 里的真相Ingress Nginx 自带 Prometheus metrics如果只依赖 wrk 的统计你会漏掉很多内部信息。重点关注这几个指标nginx_ingress_controller_requests累计请求数可以用 rate() 计算实时 QPS。nginx_ingress_controller_nginx_process_connections当前连接数和连接状态分布。nginx_ingress_controller_nginx_process_requests_totalworker 进程处理的请求数。nginx_ingress_controller_successreload 是否成功。通过 Prometheus 把 Ingress 的 QPS、延迟、连接数曲线和压测工具的统计放一起对比一旦 QPS 上不去你能立刻分辨是连接层瓶颈还是处理层瓶颈。6.4 压测容易犯的错误注意避开压测有个经典错误并发连接设得很大但不控制请求频率结果打出来的 QPS 很低于是得出“配置没效果”的结论。实际上并发连接大不代表 QPS 高还要看每个连接上请求的发送速率。wrk 会自动以 WRK 的方式多线程并发发请求但 wrk2 更加可控。另一个错误是忽略客户端自身的瓶颈。压测机如果只有 4 核可能压测工具自己先把 CPU 打满了QPS 上不去是压测机的问题不是 Ingress 的问题。我见过不止一次压测机单核跑满、Nginx 那边才两万 QPS最后换台高配压测机QPS 直接翻了几倍。压测机的 CPU 核数至少要和目标 QPS 的数量级匹配否则结果没有参考价值。7. 遭遇瓶颈时的排查路径与实战案例7.1 TIME_WAIT 堆积、本地端口耗尽现象压测时 QPS 曲线先上升后突然稳定在一个值不再增长服务器上ss -s显示 time-wait 数量有几万个然后出现大量connect() failed (99: Cannot assign requested address)错误。这基本可以断定是本地端口不够用了。Nginx 转发到后端时每建立一个新连接就要占一个本地端口TIME_WAIT 里的端口不会被立即复用默认要等 60 秒瞬时请求量一大端口很快就全部被占。解决方案调大ip_local_port_range比如1024 65535直接增加可用端口数。开启tcp_tw_reuse和缩短tcp_fin_timeout让端口能更快地被回收复用。从根上减少短连接数量开启 upstream keepalive让 Nginx 到后端的连接保持复用。排查命令ss -s ss -tan | awk {print $1} | sort | uniq -c | sort -rn cat /proc/net/sockstat7.2 全连接队列溢出导致超时现象客户端总是报连接超时或连接重置但 Nginx 的 CPU 和内存都不高。ss -lnt显示监听端口上的 Recv-Q 持续积压说明新连接已经进了内核队列但 Nginx 没有及时 accept。原因通常是 somaxconn 和 backlog 没配对或者 worker 数量太少导致 accept 处理不过来。还有可能是 Nginx 的单个 worker 阻塞在同步事件上比如一次同步磁盘 IO 或 upstream 响应缓慢占用了事件循环。排查命令ss -lnt cat /proc/sys/net/core/somaxconn kubectl exec ... -- cat /etc/nginx/nginx.conf | grep -i listen解决方案调大 somaxconn、tcp_max_syn_backlog、netdev_max_backlog同时保证worker_processes能覆盖 CPU 核心数。必要时开启多 accept在 ConfigMap 里通过accept-mutex参数调整或者通过模板把multi_accept on写进去让 worker 一次 accept 尽可能多的连接。7.3 TLS 握手把 CPU 打爆现象压测时 QPS 被压在很低的位置top显示 CPU 用户态使用率接近 100%但 wrk 显示的延迟并不高。用perf top看一下函数的符号主要集中在 SSL 加密库上。这种情况基本就是握手开销导致的。解决方案优先确认ssl_session_cache和ssl_session_tickets已经开启让大部分会话复用走缓存。然后确认 TLS 版本和密码套件没有使用过时的算法比如 SHA1 签名或 CBC 套件这些都偏慢。最后如果业务有大量非首次连接session cache 的命中率会直接决定 CPU 能省多少。验证命令openssl speed rsa2048 openssl s_time -connect ingress-node.example.com:443 -new7.4 软中断不均衡网卡多队列没用上现象QPS 到达一定值后某几个核的 CPU 使用率非常高其他核却很空闲。top按 1 查看每个核的使用情况你会发现软中断都集中在一个 CPU 上。原因网卡多队列没有生效或者 RPSReceive Packet Steering没有开启。Linux 默认会把所有接收到的包都放到同一个队列由同一个 CPU 处理一旦流量大了这个 CPU 就变成瓶颈。解决思路确认网卡支持多队列ethtool -l eth0查看 Combined 值。如果 Combined 只有 1尝试用ethtool -L eth0 combined 4开启多队列云服务器的网卡一般可以开。对于无法改多队列的环境可以通过 RPS 把中断处理分摊到多个 CPU 上。具体配置可以写到/etc/sysctl.d/或者 systemd 启动脚本里核心思路是把rps_cpus按 CPU mask 配置到每队列。但 RPS 在容器场景下的收益没那么大优先确认网卡队列和多核软中断是否均衡。7.5 后端连接池没生效一切白调现象所有配置都改完了压测 QPS 依然上不去Nginx 本机 CPU 不高但后端应用 CPU 极高报错连接数过多或者线程池打满。进去看 nginx.confupstream 里没有keepalive字段或者有字段但实际仍一请求一连接。这种坑最常见的原因是upstream 后面代理解析出来的是某个 Service 的 ClusterIP如果 Service 的sessionAffinity没配好或者 Pod IP 变化频繁连接池里的连接会被反复重建keepalive 等于形同虚设。另外Ingress 模板里如果缺少proxy_http_version 1.1;和proxy_set_header Connection ;upstream keepalive 也不会生效。排查时一旦发现源码模板有问题最快的做法是自定义一份 ConfigMap 中的http-snippet或者直接挂载自定义模板。但自定义模板会脱离社区默认维护路径升级 Ingress Controller 版本时可能要重新适配建议谨慎使用。7.6 metrics 与链路追踪从黑盒到白盒把网络栈和连接池都排过以后如果 QPS 仍上不去就要考虑是不是有别的隐藏依赖。比如 Ingress 接入 WebSocket、gRPC 或 HTTP/2 时连接模型完全不同。gRPC 走 HTTP/2每个连接可以多路复用QPS 的瓶颈往往在 stream 并发数上。ConfigMap 里的http2-max-concurrent-streams默认是 128尤其注意这个数值是否过小。到这种精度时建议把 metrics 的维度补齐rate(nginx_ingress_controller_requests[1m])QPS 曲线histogram_quantile(0.99, rate(nginx_ingress_controller_request_duration_seconds_bucket[1m]))P99 延迟nginx_ingress_controller_nginx_process_connections连接数、状态的实时值配合后端应用的 trace确认请求时间到底消耗在 Ingress 还是后端。链路追踪需要额外配置但在疑难问题的定位上非常值。高并发问题经常不是单一配置项造成的而是多个隐性问题叠加的结果把每个环节的可观测数据拼起来你才能还原完整链路。8. 调完以后我还有几个实战心得想分享最后说几句只会在实际操练中体会到的经验。第一性能调优不是把某一项参数调到最大而是让整个链路协调工作。我见过有人把worker-connections调到了 100 万但内核的 somaxconn 才 128连接根本进不来也见过 upstream keepalive 调得很大但后端服务每 30 秒重启一次连接全部失效。每调整一个参数你都应该问一句这个参数对应的另一端的约束是什么第二每次改动只动一个变量并且记录下来。我自己的习惯是准备一个表格里面记录日期、改了哪个配置、压测 QPS、P99 延迟、CPU 使用率、连接数、TIME_WAIT 数量。没有这个基线数据你很难判断某项改动是正向还是负向。盲目的“一次全改完”最容易导致结果无法归因出了新问题也完全不知道回滚哪一个。第三单机调优的尽头是架构层面的确定性问题。单机 Nginx 毕竟受限于硬件资源CPU 主频、网卡带宽、内存带宽都是硬上限。如果你已经把内核参数、worker 模型、TLS、keepalive 全都调到位单机 QPS 仍然离目标差很远那你要考虑的不是继续扣配置而是换更高配的硬件、用多核队列更好的网卡、或者重新审视你的请求路径上是不是有没必要的转发和加解密环节。调了这么多套 Ingress 之后我的感觉是性能调优更像是一门排障的学问而不是堆参数的学问。每个参数背后都是 Linux 内核或 Nginx 事件模型的一个真实行为你理解得越深就越能精准地找到自己系统的短板而不是盲目复制别人的“秘籍”。这套配置和排查方法希望也能帮你把单机 Ingress Nginx 的性能挖到真正的极限。
RELATED

相关推荐

dart_scope鸿蒙适配实战:作用域驱动Flutter依赖生命周期治理

dart_scope鸿蒙适配实战:作用域驱动Flutter依赖生命周期治理

开头一个 Flutter 应用跑在鸿蒙设备上,界面渲染没问题了,但业务状态却乱成一锅粥——页面 A 创建的服务在页面 B 里串用了,退出页面后定时器还在跑,全局单例越攒越多却没人清理。这种场景,做过多端适配的团队多少都经历…

📅 2026/10/20 7:09:34
扩散语言模型技术全解析:并行生成、可控性与工程实践

扩散语言模型技术全解析:并行生成、可控性与工程实践

直接从一个技术圈的老话题切入吧——早就听人争论“语言生成到底还要不要按顺序一个字一个字往外蹦”,直到这轮“数亿元”级别的融资砸下来,全球扩散语言模型这个赛道才算真正被重新定价。说实话,当看到手机生态的头部玩家和智能终端领域的巨…

📅 2026/10/20 7:09:34
YOLO11双模态改进源码解析:红外与RGB特征融合的目标检测实践

YOLO11双模态改进源码解析:红外与RGB特征融合的目标检测实践

简介:一套YOLOv11多模态输入检测项目资源,面向毕业设计及科研场景,核心解决红外(IR)与RGB可见光图像共同识别问题,通过融合不同光谱信息,提升夜间、低照度、烟雾等复杂环境下的目标检测精度与鲁…

📅 2026/10/20 7:09:34
MORE NEWS

更多资讯

📰

kubeadm部署Kubernetes V1.21.1集群:从零搭建到故障排查全指南

接手过各种规模的K8s环境,从单机实验到生产集群都踩过一遍坑之后,我必须说:kubeadm依然是现阶段部署 Kubernetes 最省心、最不容易把自己绕晕的路径,尤其是 2021 年发布的 V1.21.1 这个版本,处于容器运行时切换的关键过…

📰

进程空中技术:在内存中直接加载并运行exe的完整实现

简介:这份资源围绕进程空中技术(RunPE / Process Hollowing)展开,面向安全研究人员、逆向工程师以及希望深入理解 Windows 底层机制的学习者,帮助解决在不将 exe 写入磁盘的前提下于内存中动态加载并执行代码的问题。压…

📰

MyBatis-Plus多数据源实战:动态数据源配置与原理详解

0. 开场:如果项目里只有一个数据库,这篇文章可以直接关掉先说个直白的判断:如果你的业务系统只连一个库,那多数据源配置对你来说就是纯粹的增加复杂度,别被“轻松实现”这四个字忽悠着盲上。但如果你遇到的是这些场景&…

📰

IDA Pro高效逆向:5个隐藏功能助你告别sub_xxx信息废墟

用IDA Pro做逆向分析的人里,十有八九都卡在同一个地方:不是反汇编窗口看不懂,而是信息量太大,代码里全是sub_xxx、dword_xxx,工作台上一片灰色废墟。很多朋友来跟我聊效率问题,说别人几十分钟能讲清楚一条调…

📰

CircuitPython驱动SSD1675墨水屏:从环境搭建到三个实战案例

我最近在折腾一块 250122 的墨水屏,驱动包正是 adafruit-circuitpython-ssd1675。这个小东西解决了一个非常具体的问题:在 CircuitPython 生态里,用十几行代码就能把 SSD1675 电子纸点亮并显示内容。相比裸写寄存器、对着 datasheet 翻 VCOM、…

📰

空间数据:数字孪生的底线,而非可选项

2. 空间数据是“孪生”的底线,不是可选项2.1 一个“会动的PPT”是怎么造出来的我见过太多所谓的数字孪生项目,演示的时候惊艳全场,一查底层数据,连经纬度都对不上。它们的典型生产流程是这样的:先找设计院要一套BIM模型…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬