后端架构师三步调优,服务器吞吐量翻倍
|
去年2月份,我接手某银行核心账户系统的压测优化——阿里云ECS c7.4xlarge(16核32G),Spring Boot 2.7.18 + MySQL 8.0.33单主架构,原TPS卡在1860,平均响应延迟214ms,P99超1.8s。客户凌晨三点打来电话问“是不是数据库挂了”,我说不是,是连接池配错了。 第一步调优:把HikariCP最大连接数从30硬生生拉到96,但没动最小空闲值,结果凌晨三点监控告警狂闪——ActiveConnections峰值冲到91,IdleConnections掉到2,线程池饥饿导致大量请求在GetConnection阶段排队。这事儿怪我,当时照着《高性能Java系统》第117页抄参数,忘了那本书用的是PostgreSQL+连接复用率82%,而我们MySQL的事务锁粒度和连接复用率才63%——后来翻Git提交记录,发现上个架构师在2022年8月就把maxLifetime从30分钟砍成5分钟,就为防连接老化,可谁也没测过这个改动对池子水位的影响。失败案例就摆在这儿:盲目扩连接池,吞吐量反跌12%。
文章配图,仅供参考 第二步换Netty。不是全量替换,只把支付回调网关的HTTP入口从Tomcat迁到WebFlux+Reactor Netty,JVM堆内存从2G压到1.2G,Young GC频率从每38秒一次变成每112秒一次。这里有个别人没写过的细节:我们在Netty的ChannelOption.SO_BACKLOG设成2048后,发现Linux内核net.core.somaxconn仍是128——于是三次握手SYN队列满溢,客户端看到大量“connection refused”却误以为是业务异常。临时加了个systemd服务启动前脚本去改sysctl.conf,这步漏了,整整耽误两天排查。实测数据出来了:后端架构师三步调优,服务器吞吐量翻倍。 第三步更邪门——把MyBatis二级缓存开关从true改成false。为什么?因为观察到Redis集群CPU常年78%,但key空间命中率仅41%,查缓存日志发现83%的queryCacheKey都带时间戳字段,而该字段来自@SelectProvider生成的动态SQL。我们改用Caffeine本地缓存+Guava CacheBuilder.maximumSize(2000),搭配@Cacheable(key="#p0 + '_' + #p1")强制剥离时序变量。上线前三小时,DBA发来微信:“慢SQL从47条降到3条,但MySQL InnoDB Buffer Pool Hit Rate从91.2%掉到87.6%……你们真不担心?”——我回:“怕啥,我们连Buffer Pool都没调大,等下次扩容再说。” 新技术真香。 去年2月份那次压测,从1860 TPS干到3790 TPS,耗时11天,中间重启服务7次,改配置项32处,重写SQL 14条,被运维骂了5回。但没人提的是:翻倍的吞吐里有21%来自JVM G1GC的-XX:MaxGCPauseMillis=100参数——这个值在测试环境跑得稳,在生产环境却让Full GC频率翻倍。所以现在每次调参前我都带一台灰度机器跑48小时连续负载。下周一我就要去杭州跟蚂蚁的哥们蹲着看他们怎么搞RocketMQ消息积压削峰,他们说新出了个Broker级实时限流插件,连ConsumerGroup都不用重启……要不要试试? (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


后端架构师聚首:共探容器化技术与云原生未来