7.1 性能调优:JVM与连接器参数


文档摘要

7.1 性能调优:JVM 与连接器参数 本节摘要:调优不是抄参数,是按层观测再动刀。本节从一次压测的三个数字出发,按"堆内存与垃圾回收、连接器三闸门、线程与下游匹配"三层走完调优流程,最后讲单机到顶之后的出路——集群横向扩展与会话复制的取舍。每一层都先给观测指标再给参数动作,保证每个改动有据可依。 回程与保养的第一课。全册的管道知识在这里接受综合运用:3.2 的三道闸门、4.3 的连接池算术、5.3 的资源调度,全部会在调优流程里再次出现——只是这次视角从"认识管道"变成"给管道提速"。 压测台上的三个数字 一套订单服务上线前的压测报告里,有三个数字最要命:每秒完成请求数 1200、平均响应 210 毫秒、错误率 3.7%(其中大半是连接被拒)。

7.1 性能调优:JVM 与连接器参数

本节摘要:调优不是抄参数,是按层观测再动刀。本节从一次压测的三个数字出发,按"堆内存与垃圾回收、连接器三闸门、线程与下游匹配"三层走完调优流程,最后讲单机到顶之后的出路——集群横向扩展与会话复制的取舍。每一层都先给观测指标再给参数动作,保证每个改动有据可依。

回程与保养的第一课。全册的管道知识在这里接受综合运用:3.2 的三道闸门、4.3 的连接池算术、5.3 的资源调度,全部会在调优流程里再次出现——只是这次视角从"认识管道"变成"给管道提速"。

压测台上的三个数字

一套订单服务上线前的压测报告里,有三个数字最要命:每秒完成请求数 1200、平均响应 210 毫秒、错误率 3.7%(其中大半是连接被拒)。三个数字对应三个不同的问题,也对应管道上的三个不同站点——这就是调优的起点:先看数字分类,再决定动哪一层

响应 210 毫秒偏慢但可接受,说明瓶颈多半不在连接器(连接器问题通常表现为被拒或超时,而非均匀变慢);3.7% 的被拒指向 3.2 的等待队列与连接上限;而吞吐卡在 1200 上不去,要看线程是否已满配、下游数据库是否到顶。三个数字三条线索,逐层下钻。

图 7-1:调优分层地图——每层先观测再动刀

图 7-1:调优分层地图——每层先观测再动刀

第一层与第二层:闸门和窗口

第一层先动。210 毫秒的平均响应里,线程转储显示二百个 exec 线程一百九十多个在等数据库返回——瓶颈根本不在 Tomcat,在一条没走索引的慢查询。把查询从 180 毫秒优化到 30 毫秒,吞吐自动翻倍,闸门一个没动。这一步省下的功夫比任何参数调优都大,也是"调优先调下游"的经典案例。

第二层处理被拒。错误集中在压测峰值段,连接数曲线触到 maxConnections 后新连接进不了城。这台服务长连接偏多,把连接容量提到一万六、门外队列放宽到两百,被拒率应声落千分位。参数怎么写 3.2 全有,这里给的是判断顺序:被拒才动闸门,均慢不动闸门——均匀变慢去第一层查线程与下游,闸门调得再大也只是让请求换个地方排队。

第三层:堆与垃圾回收

JVM 层的调优动作全部落在 2.2 说过的 setenv 脚本。先观测:开启垃圾回收日志,看停顿与节奏。

# bin 目录 setenv.sh:观测优先的 JVM 配置 JAVA_OPTS="-Xms2g -Xmx2g \ -XX:+UseG1GC -XX:MaxGCPauseMillis=100 \ -Xlog:gc*:file=logs/gc.log:time,uptime:filecount=5,filesize=20m"
[2026-08-21T15:04:12.318+0800][12.345s] GC(25) Pause Young (Normal) 1024M->128M(2048M) 3.2ms [2026-08-21T15:04:40.918+0800][40.945s] GC(26) Pause Young (Normal) 1088M->135M(2048M) 3.8ms

两行日志给出健康画像:年轻代回收把堆从约 1G 压回一百多兆(大量短命对象被及时回收,健康);单次停顿三毫秒上下(对网页服务无感,健康)。不健康的形态对照着记:停顿几十毫秒且越来越长,考虑换回收器或调停顿目标;老年代只涨不落,先怀疑泄漏(7.4 的三步定位),此时调参数是掩耳盗铃。

堆大小怎么定?经验起点:2 到 4G,新生代留足。更大不一定更好——堆越大单次回收扫描面越大,停顿反而恶化。让数据说话:压测时观察回收频率与停顿,频率过高说明堆小,停顿超标说明要换策略,都不是就别动。初始值与最大值设成一致(如上例的 2g 配 2g)可以避免运行期扩容抖动,这是廉价的稳定性收益。

单机到顶:横向扩展

三层调尽,单机吞吐仍是定数,下一步是加机器。加机器立刻引出新问题:用户的会话在 A 机上,下一个请求被负载均衡分到 B 机,登录状态丢了。两条出路。

其一,会话复制:集群配置里启用内置的会话复制,节点间组播同步会话。配置不复杂,代价是网络流量与序列化开销随节点数放大,适合三五台的小集群。其二,会话外置:把会话存到独立的缓存服务,Tomcat 侧配对应的会话管理器或应用直接用无状态令牌。这是云原生的主流答案——应用无状态,扩容缩容随心,不绑定内置复制。

<!-- server.xml:小集群会话复制示例 三节点内可用 --> <Cluster className="org.apache.catalina.ha.session.SimpleTcpCluster"/>

一条提醒收尾:无论哪条路,先确认应用真的需要会话——很多"需要"只是历史习惯,把状态外移或改造成令牌,集群复杂度直接消失。能无状态就无状态,这是横向扩展的最高心法

JVM 参数速查与两个误区

参数 作用 经验起点
初始堆与最大堆 划定堆范围,两值相等免抖动 2 到 4G 按内存预算
回收器选择 吞吐优先或停顿优先 大内存选 G1 系
停顿目标 给回收器的软性目标 一百毫秒量级
回收日志 观测一切的前提 必开,轮转五份
时区与编码 多系统对表的地基 与业务库一致

两个高频误区收尾。误区一:"堆越大越好"。单次回收要扫描的存活对象随堆增长,停顿反而恶化;内存富裕时宁可留给页缓存与直接内存。误区二:"抄别人的参数"。参数的最优值取决于对象分配速率、请求时长、内存预算三件事,两个都不同的服务抄同一套参数,如同两人互换药方——观测数据才是唯一的处方依据。

本节要点回顾

  • 三个数字三条线索:被拒查闸门、均慢查线程与下游、吞吐卡顶查下游容量。
  • 调优分层下刀:线程与下游、连接器闸门、JVM 内存,一次一层一个参数。
  • 下游慢是常见根因:线程都在等数据库时,任何容器参数都救不了。
  • 垃圾回收看两指标:停顿时长与回收节奏,健康锯齿胜过一切理论值。
  • 横向扩展先问会话:小集群内置复制,云原生会话外置,能无状态最好。

保养第二课:让管道看得见。下一节讲监控指标与那六类日志——没有观测的调优都是盲调。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U