线上压测、系统性能优化

一、前提

最近公司在搞活动,预计会来一波业务高峰,流量会达到平时的6倍,所以各个系统都在优化、压测。
我所负责的系统为支付系统,也就是整个链路的最下游,目前支付系统支付接口TPS1600,10个节点,单节点TPS160,压测目标是3000+,这差了将近2倍,基于此背景下开始各种优化


二、优化

先看下支付流程,很简单:
在这里插入图片描述
代码层面没有复杂逻辑,整个链路比较简单,优化的余地很小,

主要的优化点有:
1、调用外部接口时,去掉了一些无用字段,减少网络开销
2、对redis缓存做了本地二级缓存(读取路由配置)
3、入库时有两个字段填充依赖于查询外部接口,已改为异步填充(支付完成后填充)

第一轮压测:
代码逻辑上也没有优化的余地了,于是又线上压测了一次,TPS从1600增加到了1700,效果很不明显

第二轮压测:
于是乎开启了王能大法:加机器,从10个节点扩到15个节点,又压测了一轮,TPS达到了2200,离目标又近了一步,随后有加了5个节点,目前已达到了20个节点,压测结果将然降了50TPS!分析了下这应该是数据库、中间件或者是外部接口有性能瓶颈。

1、检查了下数据库连接池,默认是20,以前是10个节点也就是200个链接,现在是20个节点400个链接,可能链接数太多导致,数据库使用的是polardb(阿里云的mysql plus版),官方建议是cpu核数*2+1,所以给每个节点的最大数据库连接池设置为10

2、压测期间项目大量报tomcat等待超时,获取不到链接,经排查支付项目所以来的网关项目tomcat配置有问题,其max-thread竟然配置的只有100,导致支付项目同步调用网关项目被hang住,当超过100线程时,支付项目的线程会在网关项目的线程池中等待,由于网关项目是请求三方的,同步请求时间较长,导致支付项目等待的线程大部分超时报错。将max-thread调制到1000后,tps提升了25%。期间也调整过800和1200,发现1000性能最佳,机器的配置是4核8G物理机。

第三轮压测:
基于第二轮压测后的两个改动点,有压测了一次,TPS达到了2800(果然是外部系统tomcat线程数太小导致同步请求被hang住)。
压测老师反馈压测经常会有卡顿现象,这一看就是fullgc进行了stw,打开监控平台看了下,压测期间竟然没有full gc产生,(而且近3天内也没有发生过full gc),到时young gc非常频繁,(图中波峰为压测期间)
在这里插入图片描述
经查询,younggc全程stw,这就有点坑了,其实支付项目属于young gc型,因为每一笔支付请求过后,整个链路创建的对象基本上都会回收,基本上都是方法内变量操作,没有大对象,基于这个前提下,我们把年轻代的空间从1G扩到2G,老年代从3G减少到2G,方法区从128M扩到256M
参数如下:

-server -Xms4608M 
-Xmx4608M 
-Xmn2048M 
-XX:PermSize=256M 
-XX:MaxPermSize=256M 
-XX:TargetSurvivorRatio=60 

还有一个坑点,之前的JVM参数没有设置-Xmn,导致堆内存频繁收缩,最坑的是设置了-XX:SurvivorRatio=1,这个参数是年轻代Eden区与两个Survivor区的比值,设置为1的话表示1:1,如果不设默认是8:1:1(Eden:from:to),赶紧将其去掉

第四轮压测:
基于第三轮压测后的JVM参数调优,又进行了第四轮压测,性能竟提升了15%左右,young gc明显减少,同时TPS达到了约3300,性能压测已过,来一张图看的更明显:
在这里插入图片描述
22:00点为JVM参数调整前,可以发现young gc很频繁,22:00-22:40之间设置新的JVM参数并进行压测,可以从22:40之后跟22:00之前的曲线对比,JVM参数调整后 young gc明显少了很多。在看下堆内存使用情况:
在这里插入图片描述
22:40后内存收缩次数明显减少。之前没有制定最小内存时(-xms),最大内存没有生效,当制定了-xms=-xmx时(最小内存=最大内存)时,最大内存才达到了使用效率

第五轮压测:
疏忽了一点,也就是日志打印,这点很关键,目前项目采用的是logback同步打印日志,级别为info,从监控上看,压测期间磁盘写入有大量抖动,日志写盘造成的,在从elk中分析日志,发现部分请求写日志竟高达3s,而且时间点与磁盘抖动时间点吻合,立刻将日志打印改成了异步,看了下logback异步打印的原理是将日志放到了ArrayBlockQueue里,启了一个异步线程从队列中取日志,往磁盘里刷,而ArrayBlockQueue默认的大小是256,这压测场景下如果刷盘的速度比写入的满,队列很快就满了,对其大小改成了8096,如果超过这个数,则降级处理(丢弃),同时将系统的日志打印级别改成error,降低日志数量,以及降低日志丢弃的风险。配置如下:

 <appender name="RollingFile_Async" class="ch.qos.logback.classic.AsyncAppender" neverBlock="true">
        <queueSize>8096</queueSize>
        <neverBlock>true</neverBlock>
        <appender-ref ref="RollingFileAppender"/>
    </appender>
    
	<root level="info">
        <appender-ref ref="RollingFile_Async"/>
    </root>

经压测了,TPS提高了25%,TPS达到了4200,可见并发场景下同步写日志被阻塞主线程有多么可怕

三、总结

最终接口TPS达到了4200,同时对支付入口做了限流、降级操作保护系统

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值