☰
从4.8万到10万QPS:K8s Ingress Nginx网关压测调优全复盘
2026/10/23 6:54:25 网站建设 项目流程

接手过一个模拟项目X的网关压测,K8s集群里跑的Ingress Nginx Controller,默认配置装完,8核节点压到4.8万QPS就开始“脸红脖子粗”,P99延迟从3ms抖到80ms,怎么看都配不上“Nginx性能好”的名声。后来花了两周逐步调参,最终在同一台节点上稳定跑到10.2万QPS,P99回到个位数毫秒。这篇内容就是那次调优过程的完整复盘,适合正在做K8s网关、业务入口,或者单纯想把Ingress Nginx单机性能榨干的SRE、运维和平台工程师参考。我会把瓶颈拆解、内核参数、核心ConfigMap配置、TLS成本控制、压测排障链路全部串起来讲,每个改动都说明为什么改、改了会有什么代价。

1. 先搞清楚瓶颈:默认配置为什么连5万QPS都费劲

1.1 从一次真实业务压测事故说起

那次压测的触发点很普通:大促前两周,业务方要把支付回调、商品详情、订单查询三个核心接口的压测目标定到单机Ingress 10万QPS,并且要求P99延迟不得超过20ms。当时我以为这不是什么难事,Nginx本身就是主打高并发的软件,10万QPS在裸Nginx上确实不是什么神话。结果压测一跑起来,问题全冒出来了。

默认的Ingress Nginx部署方式下,一个Controller Pod里跑着Go控制面和Nginx worker进程。Go控制面负责监听K8s资源、生成nginx.conf、执行reload,流量本身全走Nginx worker。我们当时用的是8核节点,Pod的CPU limits也给了8,结果压到4.8万QPS的时候,Nginx worker CPU已经到86%,但延迟直线上升,压测端开始大量出现超时。更诡异的是,用top看整体CPU并没有打满,有一个核心的软中断(softirq)占用却长期在90%以上。用mpstat -P ALL 1一看,明显是单核打满、其他核看戏。

这个现象给了我第一个教训:Ingress Nginx的性能瓶颈是分层的,不能只盯着Nginx配置。CPU没有整体打满,可能是软中断分配不均;连接数上不去,可能是内核参数不允许;Nginx worker自己活得很累,又可能是容器CPU throttle或者连接池配置不合理。

1.2 三类瓶颈层:容器资源、内核协议栈、Nginx配置

我把这次调优涉及的瓶颈归纳成了三个层次,后面所有的操作都围绕这三层展开:

第一层是容器资源层。Pod的CPU requests/limits设置不合理,或者节点上多个Pod争抢CPU,都可能导致CPU被cgroup限制,Nginx worker明明想跑满却跑不上去。还有一个很多人忽略的点:Nginx worker_processes默认是auto,它读取的是容器cgroup的CPU配额,而不是节点物理核数。如果你limits只写了2,那Nginx在容器里只会看到2个可用CPU,哪怕节点是64核,它也只会起2个worker。

第二层是内核协议栈层。Nginx再快,数据也要从网卡经过内核协议栈到达用户态。somaxconn过小会导致accept队列溢出,tcp_max_syn_backlog过小扛不住突发SYN,文件描述符限制不够就会出现“too many open files”,TIME_WAIT过多会耗尽本地端口,这些都会在10万QPS级别被放大成致命问题。

第三层才是Nginx配置层。包括worker进程数、单个worker的最大连接数、keepalive连接池、TLS会话缓存、超时与缓冲参数、日志与gzip的CPU开销等。这一层是“配置秘籍”的主体,但前提是第一层和第二层已经打好底子,否则Nginx配置调得再漂亮,底层也接不住。

1.3 "Nginx很强"不等于"Controller很强":两层架构的分工误区

在K8s生态里有一个常见误解,不少人以为Ingress Nginx性能不行,质疑它是不是比裸Nginx弱很多。实际上Ingress Nginx仍然是Nginx/OpenResty在转发流量,数据面性能底子没问题,真正的差别在于它加了一层Go控制面,负责监听、模板渲染、动态reload。控制面的负载非常轻,瓶颈几乎不在它身上。

但正因为有这层控制面,很多人调优时把目光放在了Controller的Deployment副本数上,试图通过多副本横向扩容来提升性能。这当然有效,但如果你只扩容副本、不调Nginx配置,每个副本还是会各自浪费资源。反过来,如果你把单副本的Nginx配置调好了,多副本只是纵向扩容的补充,而不是性能差的救命稻草。

我的目标很明确:先把单副本、单节点的纵向性能压到10万QPS,再谈副本扩容。这条路走通之后,多副本自然就变得很从容了。

2. 打地基:节点、内核与容器的三层准备

2.1 网卡多队列与软中断分散:CPU不被中断抢占

前面提到的那次压测,第一眼看到的现象是单核softirq打满。这里解释一下为什么:网卡收到数据包后,网卡驱动会在内存中填充数据,然后通过硬中断通知CPU处理。如果网卡队列只有一个,或者中断没有均匀分发到多个CPU,那么所有收包软中断都会压在一个CPU上。8个Nginx worker别的没事干,就一个核在疯狂处理软中断,QPS自然上不去。

解决思路是让网卡多队列和CPU软中断尽量分散。在物理机上,用ethtool -l eth0可以看到网卡当前的队列数,再用ethtool -L eth0 combined 16把队列数设置成16,同时配合irqbalance服务把中断号均匀绑定到不同CPU。云环境下的虚拟网卡不一定允许这些操作,但至少应该在压测前确认网卡队列支持情况。

这一步做完之后的验证方法很直观:再跑一次mpstat -P ALL 1,软中断应该均匀散布在多个核上,而不是集中在一两个核。我当时修完这一项,QPS直接从4.8万涨到了5.8万,还没动任何Nginx配置,就涨了20%。很多人在默认配置下压测遇到瓶颈,第一反应就是加副本,其实很有可能是软中断分配不均这种底层问题。

2.2 内核参数清单:连接数的物理上限

第二个要解决的是内核协议栈的承载上限。K8s节点的sysctl默认值通常比较保守,不适合高并发网关场景。以下是我在压测节点上实际改过的一组参数,列成表格供参考:

参数默认值常见范围推荐值(网关场景)作用
net.core.somaxconn409665535Nginx listen队列长度上限,过小会丢连接
net.ipv4.tcp_max_syn_backlog1024或204865535半连接队列上限,抗突发SYN洪峰
net.core.netdev_max_backlog100065535网卡驱动队列积压上限
fs.file-max较小2097152或更高全系统文件描述符上限
net.ipv4.ip_local_port_range32768-609991024-65535本机发起连接的源端口范围
net.ipv4.tcp_tw_reuse01允许复用TIME_WAIT中的连接(仅出站连接)
net.ipv4.tcp_fin_timeout6030缩短TIME_WAIT进入回收的等待时间

这里要特别说明两点。第一,net.ipv4.tcp_tw_reuse只对Nginx作为客户端去连接后端服务时有效,因为TIME_WAIT是主动关闭连接的一方产生的。Nginx转发请求后主动关闭上游连接,才会产生TIME_WAIT,这时候tcp_tw_reuse才能发挥作用。如果后端是短连接且QPS很高,每个请求都会产生一个TIME_WAIT,不处理的话源端口很快就耗尽了。

第二,tcp_tw_reuse在NAT场景下要谨慎开启,因为复用连接时可能会出现序列号不一致的问题。K8s里如果后端Pod通过NodePort暴露,流量经过了NAT,就需要评估风险。我的实际做法是:先开启,观察一段时间是否有连接错乱,没有就保留,有问题就改回0,靠调大ip_local_port_range来缓解端口耗尽。

修改sysctl的标准操作是写个/etc/sysctl.d/99-ingress.conf,然后执行sysctl --system。注意这需要节点级权限,如果用的是托管集群,可能要联系平台侧调整。

2.3 容器资源配额:limits不是越大越好,也不是越小越省

接着是Controller Pod自身的资源设置。我见过很多人把Controller的limits写得特别小,觉得Ingress路由很轻量;也见过有人直接把limits写满整个节点,结果其他Pod没地方跑。这两者都极端了。

Ingress Nginx的Pod资源配额,核心是CPU。我们的实测数据是:8核CPU、8GiB内存的limits,足够支撑10万QPS的转发+常见TLS负载。如果你的limits小于4核,建议先提到4或8再压测,否则后续调Nginx参数时,很难判断性能瓶颈到底在Nginx配置还是容器CPU被限制。

一个很容易踩的坑是CPU throttle。K8s的CPU limits用的是CFS配额,Pod的CPU使用率一旦触及limits,就会被强制节流(throttle),表现为延迟毛刺、P99抖动,但top看到的CPU占用可能还在50%-70%。我当时就遇到过:limits设4核,压测时Nginx worker CPU平均只有60%,但P99从8ms突然飙到40ms,后来查/sys/fs/cgroup/cpu.stat,发现throttled_time非常大,才意识到是CPU被节流了。所以压测时不要只看top,要额外注意:

cat /sys/fs/cgroup/cpu.stat | grep throttled

如果nr_throttled一直在增长,说明容器CPU已经被卡住了。要么把limits调大,要么把压测目标分摊到更多副本上。对于10万QPS目标,我最终用的是requests=4、limits=8,既保证了调度时不轻易超卖,又给瞬时流量峰值留了余量。

3. 核心ConfigMap调优:一条一条讲清楚为什么要改

3.1 worker-processes与max-worker-connections的配合公式

Ingress Nginx的全局配置集中在ConfigMap里,默认值覆盖了最基本的可用性,但性能参数普遍偏保守。先说两个最核心的:worker-processes和max-worker-connections。

worker-processes控制Nginx worker进程数量。默认是auto,前面说过它会读容器CPU配额。如果你确定节点物理核数是8或者16,我建议直接显式写数字,不要依赖auto。一个常见的经验公式是:

worker-processes = min(节点物理核数, 16)

为什么不能无脑等于核数?因为worker进程太多会造成进程频繁切换,CPU上下文切换开销反而拉低吞吐。8核就写8,16核可以写8或12,超过16之后收益很小。我压测的8核节点写的就是"8"。

max-worker-connections是单个worker进程能同时维持的最大连接数。这个参数很多人直接给65535,然后就不管了。但真正合理的设定依赖你对并发连接数的估算:

并发连接数 ≈ QPS × 平均响应时间 + 客户端长连接保有量 + 上游keepalive连接数

举个例子:QPS=10万,Nginx转发请求到后端并返回的平均耗时是2ms,那么瞬时在途请求大约是100000×0.002=200个。这部分不大,大头在keepalive长连接上。如果客户端开启HTTP长连接且并发连接数高达几万,每个worker都要分摊一部分,所以max-worker-connections设成65535、甚至更高都合理。注意Nginx本身还受文件描述符限制,系统层要同步调大fs.file-max和容器进程的ulimit。

对应ConfigMap片段:

data: worker-processes: "8" max-worker-connections: "65535"

改完以后执行kubectl rollout restart deployment/nginx-ingress-controller或者等待自动reload。验证方法看Nginx状态页:

curl -s http://127.0.0.1:10246/nginx_status

观察Active connections和Reading/Writing等数值,看是否随压测压力同步变化。

3.2 全链路keepalive:不只调一个客户端超时

很多人都知道要在Ingress上开启keep-alive,但容易漏掉上游连接池这一环。Ingress Nginx转发到后端服务时,如果每次请求都新建TCP连接,10万QPS下会产生海量的TCP握手和TIME_WAIT,压力全部转嫁到内核协议栈。所以全链路keepalive至少包含三段:

第一段是客户端到Ingress Nginx的keepalive。ConfigMap里对应两个参数:keep-alive-requests表示单个客户端长连接最多能复用的请求数,keep-alive-timeout表示空闲连接保留时长。默认值通常够用,但在高并发下建议把keep-alive-requests从默认提升到10000,keep-alive-timeout保持60到75秒即可。

第二段是Ingress Nginx到后端的upstream keepalive。这个是关键,对应三个参数:

  • upstream-keepalive-connections:每个upstream保留的空闲长连接数,默认值偏小,我调到了2048
  • upstream-keepalive-requests:单个上游连接最多复用的请求数,默认1000,我调到10000
  • upstream-keepalive-timeout:上游空闲连接保留时间,默认30秒左右,可以调到60秒

顺带说一句,upstream-keepalive-connections并不是越大越好,因为保留的长连接也是资源。它需要同时覆盖后端Pod数量和后端支持的最大连接数。如果后端服务本身连接数上限很低,你把Ingress侧调得很大也没有意义,反而增加Nginx和后端的负担。

第三段是HTTP/2多路复用。如果客户端支持HTTP/2,一个TCP连接上可以同时跑多个请求,这会显著减少客户端连接数量。ConfigMap里enable-http2默认是true,保持即可。

3.3 超时、缓冲与请求体:隐性开销处理的取舍

超时和缓冲参数是调优时最容易“抄错”的一类,因为每个人的业务场景不同。我在这次10万QPS压测里用到的几个核心参数和理由放在下面这张表里:

参数推荐值原因
proxy-connect-timeout10后端建连超时,太长会在后端异常时卡住worker
proxy-read-timeout60等待后端响应的超时,按业务最慢接口的P99设计
proxy-send-timeout60后端读取请求体的超时
client-header-buffer-size16k默认通常较小,请求头复杂时容易触发多余缓冲分配
large-client-header-buffers4 32k与上面配合,减少大请求头场景下的临时缓冲频繁分配
client-body-buffer-size1m请求体缓冲,设太大容易内存浪费,设太小会触发临时文件IO

这里要强调的是,全部照抄我的值并不一定适合你的业务。比如proxy-read-timeout,我做压测的接口都是几十毫秒返回的,60秒只是兜底;如果你的业务里有慢接口,这个值需要单独调大,否则会出现偶发504。

proxy-buffering也值得单独说说。默认开启时,Nginx会把后端响应缓冲到内存再发给客户端,这对性能有正向帮助,因为Nginx可以快速释放后端连接。但如果你跑的是超大响应体或流式接口,缓冲反而会占用内存和延迟,可以按Ingress annotation单独关闭,不建议全局关。

3.4 日志与压缩:高频IO与CPU的第一降耗点

在10万QPS量级,日志和压缩的开销会被放大得很夸张。默认的log-format-upstream会把大量字段拼成一行,每个请求都写一次,磁盘IO和CPU字符串处理都是额外成本。而gzip每压缩一个响应,都会吃掉CPU周期。

这次压测里我做的第一个改动是关闭access log:

data: disable-access-log: "true"

直接在ConfigMap里禁用,压测日志完全丢掉,QPS提升非常明显。不过生产环境不建议长期全关,因为排障需要访问日志。折中的方案是用更精简的log-format-upstream替代默认格式,只记录时间、状态码、请求路径、上游耗时,并且让日志走标准输出到容器日志收集器,不直接写本地磁盘。

压缩方面,gzip默认开启且级别偏高,我压测时直接把gzip-level降到了1,并把gzip-types限制在text/css、application/javascript等少数文本类型,图片、视频等已经压缩过的内容不做重复压缩。如果环境支持,可以开启enable-brotli: "true",Brotli在相同压缩比下CPU开销在某些场景比gzip更可控,但也要实测对比,不能无脑开。

还有一个小细节:动态压缩对高频接口性价比很低,因为大部分响应体的内容可能都是可预测模板。更好的方案是在业务侧做静态压缩,Ingress直接透传,CPU开销几乎为零。

4. TLS成本控制:目标10万QPS必须跨过的第二道坎

4.1 一次握手实际要消耗多少CPU

TLS是性能压测中最容易低估的杀手。一次完整的TLS握手,尤其是ECDHE密钥交换,需要执行椭圆曲线点乘等非对称计算。虽然现在CPU都支持AES-NI等硬件加速,但握手本身的计算开销依然远高于普通HTTP请求转发。

我做过一个简单对照实验:同一个8核节点、同样的配置,纯HTTP转发能跑到9万QPS左右,一旦全部走HTTPS新连接握手,QPS会掉到不到一半。原因很直观:每个新连接进来都要做一次握手,握手消耗的CPU可能是普通转发请求的5到10倍。如果10万QPS全是新TLS连接,CPU直接被打爆,Nginx配置怎么调都救不回来。

所以TLS调优的核心思路不是让握手更快,而是尽量少握手、复用会话。

4.2 会话缓存与会话复用的正确开启姿势

Nginx侧需要开启TLS会话缓存,让一定时间内复用相同会话的客户端免去完整握手。ConfigMap中相关的参数是:

  • ssl-session-cache: "true":开启会话缓存
  • ssl-session-cache-size: "50m":缓存容量,默认10m,压测中我调到了50m
  • ssl-session-timeout: "30m":缓存有效期,默认较短,针对高复用连接可以放宽到30分钟
  • ssl-buffer-size: "16k":握手时发送的缓冲大小

开启后,客户端如果支持TLS Session ID或Session Ticket,TLS握手的第二次请求就能走简化握手,CPU开销大幅下降。但问题在于:客户端不一定每次都复用会话,很多压测工具默认也不会复用TLS会话。比如用wrk压HTTPS时,如果脚本里不带session复用逻辑,测出来的就是最坏情况,性能数据会很难看。这并不意味着生产环境一样差,你要看真实客户端的TLS复用率。

用h2load压HTTP/2时,它会主动复用TLS会话,测出来的数据更接近真实浏览器场景。生产环境建议通过监控TLS握手速率来确认会话复用率,如果握手速率过高,大概率是客户端每次请求都新建连接,这时候要考虑调大保活时间和会话缓存,或者推动客户端接入长连接。

4.3 密码套件与算法选择:性能和安全的平衡

密码套件的选择也会影响CPU占用。旧版本的Nginx配置可能还带着ECDHE-RSA-AES256-GCM-SHA384这类强套件,但它不是性价比最高的。

在兼顾安全和性能的前提下,我这次使用的是以下推荐套件配置:

ssl-protocols TLSv1.2 TLSv1.3; ssl-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl-prefer-server-ciphers on;

优先顺序是AES128-GCM,比AES256快一些,安全性在绝大多数业务场景足够。TLS 1.3默认使用更强且更快的握手,一定要放到支持的协议范围里。全套配置在ConfigMap里可以直接通过ssl-ciphers和ssl-protocols设置。

这里还要注意证书本身的性能:使用ECDSA证书比RSA证书握手更快,因为ECDSA签名体积小、验证开销低,但证书签发链支持情况需要评估。如果业务方已经用了某个公开CA的RSA证书,贸然更换成本高,可以在需要极致性能的边缘场景单独给新证书,或者把证书转到前置LB处理。

4.4 该不该把TLS卸载到前面的负载均衡器

聊到这里,很多人会问:既然TLS这么吃CPU,那干脆把证书放在Ingress前面的负载均衡器上,让LB做TLS卸载,Ingress只处理明文HTTP,是不是更好?

这个方案确实能显著降低Ingress Nginx的CPU负担。如果你的LB支持TLS终止,并且已经把证书管理、自动续期做得很成熟,那卸载到LB往往比在Nginx里做更省事。尤其是全站HTTP/2和高并发长连接场景,LB承担的握手量可能成为新的瓶颈,但那属于LB的扩展能力问题,不管Ingress的事了。

但卸载TLS也有代价:一是LB到Ingress之间的链路如果是集群内部明文HTTP,需要确保网络隔离可信;二是Ingress侧拿不到加密连接信息,有些基于TLS特征的限流或安全策略会失效;三是排查问题时链路跳数变多。我的建议是:如果Ingress就是最终网关且节点CPU可控,保留TLS在Ingress做并调好会话复用;如果后端Ingress已经需要承受大量TLS握手且CPU打满,卸载到LB是合理选择。这两种方案没有绝对的对错,核心是明确你的瓶颈到底在哪一层。

5. 从5万到10万:一轮完整压测与排障记录

5.1 压测工具选型与压测机本身的问题

要做10万QPS的压测,工具选错了会闹笑话。我这次用的组合是wrk、h2load和vegeta,各有分工:

  • wrk:主要压HTTP/1.1场景,支持多线程和连接数控制,简单高效,适合打纯HTTP和HTTPS(HTTPS记得确认会话复用行为)
  • h2load:压HTTP/2多路复用的首选,能一次建立大量HTTP/2连接,模拟真实浏览器和移动端长连接场景
  • vegeta:适合恒定压力长时间压测,结果统计做得比较完善,我用来做10分钟稳定性验证

压测机本身也容易成为瓶颈。很多人在压测机上没调内核参数,压到5万QPS时压测机自己的文件描述符或者端口先不够了。比如wrk默认每个线程创建大量连接,Linux默认的ulimit -n只有1024,不调大根本压不动。压测机至少需要把fs.file-max、net.ipv4.ip_local_port_range同步调大,再用多台压测机对目标打流量,避免单台压测机自己先被拖垮。

如果你只有一台8核压测机,还在同一台机器上跑压测工具和监控脚本,那压测数据的可信度就打折扣了。我给的建议是:压测机至少2台,每台4核以上,压测工具和mpstat、ss这些监控命令不要和目标Ingress节点混跑。

5.2 第一轮压测:CPU没用满但QPS上不去的怪事

进入正题。第一次调整完软中断、内核参数和前面列出的ConfigMap配置后,我满怀期待地开跑,结果QPS卡在7.2万左右,上不去了。top显示Nginx worker CPU总共才50%,8个核里有两个偏高、其他不活跃。CPU没顶满,QPS却先见顶,这种“资源没用满但吞吐卡死”的情况最容易让人困惑。

我当时的排查链路是这样的,这条链路也值得记录:

第一步,先用mpstat -P ALL 1看CPU分布。这时候发现硬中断和软中断已经均匀了,问题不在中断了。但同时注意到有两个CPU的%sys特别高,说明内核态在大量干活。

第二步,用ss -s和ss -nt state time-wait看连接状态。结果显示Time-Wait连接数量非常多,每秒新建连接数量接近20万,有些异常。这背后是wrk压测时没有开启keepalive复用,导致每个请求都是新建TCP连接。这既是压测方法问题,也是一个直观的信号:真实业务如果也这样高频新建连接,内核协议栈压力极大。

第三步,用dmesg看内核日志,发现大量nf_conntrack表满的报错。K8s节点上conntrack是一个常见的隐藏限制,默认表大小通常只有几十万条,高连接场景下很容易满了丢包。这一步的真实命中比我想象中来得快。

排障动作分两步走:压测端wrk加-H "Connection: keep-alive"并限制并发连接数在一个合理区间,降低新建连接速率;节点上调大conntrack表和桶大小:

sysctl -w net.netfilter.nf_conntrack_max=2097152 sysctl -w net.netfilter.nf_conntrack_buckets=524288

顺带说一下,K8s很多组件都依赖conntrack,调大前要确认安全,别把节点内存打爆。这次调整后QPS直接从7.2万跳到9.1万,问题的根源根本不是Nginx配置,而是压测方法和连接跟踪能力。

5.3 第二轮压测:QPS上去了,P99却开始抖动

到了9.1万QPS,离目标只剩一小步,但P99延迟开始变得不稳定。10分钟内,P99在7ms和35ms之间来回跳,明显有周期性抖动。我一度怀疑是后端服务扛不住,但通过后端监控看,上游的P99一直在3ms以内,问题还是出在Ingress这一层。

这次我重点排查了两个点。第一是容器CPU throttle。前面提到过,CPU limits=8时如果瞬时突发流量超过8核,cgroup会强制节流,表现为P99抖动。用cat /sys/fs/cgroup/cpu.stat一看,确实有nr_throttled增长。这说明8核在突发流量下已经有点紧张了,光是调大limits不现实,因为节点总共就那些核,更好的思路是降低瞬时突发度,比如在压测时控制并发连接增长速率,让压力不是一次性涌进来。实际生产中,这对应的是真实流量模型中突发尖峰的处理,我会在模块末尾再说。

第二是Nginx worker之间锁竞争。高并发下如果多个worker频繁争用共享锁,也会出现CPU没打满但P99抖动的现象。用perf top看了内核热点,确实看到了spinlock相关的符号占比不低。这个问题的根源之一是worker进程太多或连接分配不均,尝试把worker-processes从8降到6后,P99抖动有所缓解,但总QPS下降了一点,说明8个worker还是必要的。后来我没有强行压worker数,而是通过开启HTTP/2多路复用来降低总连接数,让每个worker的单位连接处理效率更高。最终P99回到了个位数毫秒。

5.4 最终结果与调优前后对照

最终的配置跑通后,我用三台压测机同时打这台Ingress,连续10分钟压力测试,数据如下:

指标默认配置调优前调优后最终值
单机QPS48,000102,000
P99延迟21ms8ms
CPU整体占用72%68%
软中断单核最大占用95%18%
每秒新建TCP连接数约11万约2.1万
后端P99延迟3ms3ms

这份数据只是我这次压测环境下的结果,不代表所有节点都能复现一模一样的数字。但它至少说明了一个问题:10万QPS不是靠某一个单一配置项魔法般达成的,而是底层中断分散、内核参数、Nginx keepalive链路、TLS会话复用、压测方法层层叠加的结果。每一个单点的提升都有限,合在一起才冲过10万线。

6. 结束语:关于"配置秘籍"我想再提醒几件事

这套配置跑通之后,我在团队内部把ConfigMap固化成了标准模板,后来其他业务接入时也直接复用。但有几句话我必须在最后单独拎出来说。

第一,这套调优默认你的后端响应足够快。如果后端接口P99本身就是200ms,那Ingress再强的配置也只是把排队问题隐藏在后端,QPS天花板会由上游决定,你在Ingress侧看到的不再是性能瓶颈,而是超时和排队积压。

第二,线上环境建议在10万QPS目标上留足余量。我压测达到10万QPS时CPU整体已经接近68%,如果再叠加突发流量、日志收集、故障恢复等真实因素,单机长期扛满10万是很危险的。实际容量规划建议按6到7万单机预留,超出部分用副本横向扩容。

第三,每次改ConfigMap之后,不要只看QPS有没有涨,要看错误率和P99有没有恶化。Nginx的server-snippet、http-snippet这类自定义配置很容易改坏全局,线上尽量少用。

最后分享一个实用小技巧:压测结束后把ConfigMap里每一项改动的记录和当时的QPS、P99对应起来,形成一张自己的调参对照表。不同业务对延迟和吞吐的敏感度不一样,我的“秘籍”只能作为起点,真正属于你的配置需要用自己的流量模型反复压出来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询