前言
最近对正在负责的一个系统做了一个压测,在此复盘了这次压测的整体流程,以及需要关注的指标,由于很多数据指标没有被保留,因此没有完全还原场景,后续再来完善吧,这篇就做入门指引吧。
概览
压测指标 系统优化点 JVM模板 优化前后指标对比
1.压测指标
压测的直播如下
| 指标 | 期望值 | 描述 |
|---|---|---|
| cpu.idle(cpu剩余) | min>=30% | 即cpu的最高占用率不能高于70% |
| lantency(接口耗时) | avg <=50ms | 对于高并发的系统,QPS要求比较高的,一般lantency要控制在10ms以内 |
| mem.used(内存使用率) | avg<=80% | 内存使用率一般不要超过能机器80% |
2.系统优化点
系统优化一般是从如下几个点去考虑,这里先简单介绍下对应的工具,后续会通过场景再现讲解。工具的地址会在文章末尾给出。
Arthas:阿里开源的一个性能分析工具,全方位的定位性能问题Arthas:https://arthas.aliyun.com/doc/ useful-scripts:一些非常牛逼的脚本,可以帮助你解决很多线上问题 show-busy-java-threads:这里重点提一下这个脚本,可以协助我们解决线程的问题
2.1.lantency
接口响应耗时较长,这里首先需要定位到耗时的代码位置,使用
Arthas
。

trace com.xiaoju.manhattan.messenger.controller.MsgPushController pushMsg
这里使用Arthas
的trace命令定位到耗时较长的接口,然后可以逐步往下跟踪找到对应的方法,进行优化。
降低接口耗时,提高QPS的方案,一般来说就是采用多级缓存以及异步化的方式。
常用的本地缓存框架:GuavaCache和caffeine 分布式缓存一般使用Redis:记得设置超时时间,rediskey的值不宜过大
日志
对于QPS要求比较高,以及lantency要求比较高的,日志一定要使用异步日志。
引入包: "com.lmax:disruptor:3.3.6" log4j2.xml配置
下面附上我这边的配置吧,includeLocation
是用来打印行号的,这个对性能还是比较大的,会占用比较高的cpu资源,后续再来完善具体的原因
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Properties>
<Property name="SERVICE_NAME">messenger-api</Property>
<Property name="LOG_HOME">../logs/messenger/${SERVICE_NAME}</Property>
<Property name="ENCODING">utf-8</Property>
</Properties>
<Appenders>
<!-- INFO日志 -->
<RollingRandomAccessFile name="INFO_FILE"
fileName="${LOG_HOME}/business.log"
filePattern="${LOG_HOME}/business.log.%d{yyyyMMddHH}" immediateFlush="false" append="false">
<FinBamaiLayout/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${LOG_HOME}">
<IfFileName glob="business.log.*"/>
<IfLastModified age="30d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- ERROR日志 -->
<RollingRandomAccessFile name="ERROR_FILE"
fileName="${LOG_HOME}/error.log"
filePattern="${LOG_HOME}/error.log.%d{yyyyMMddHH}" immediateFlush="false" append="false">
<FinBamaiLayout/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${LOG_HOME}">
<IfFileName glob="error.log.*"/>
<IfLastModified age="60d"/>
</Delete>
</DefaultRolloverStrategy>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
</RollingRandomAccessFile>
<!-- public消息回执的日志 -->
<RollingRandomAccessFile
name="public_log" fileName="${LOG_HOME}/public.log"
filePattern="${LOG_HOME}/public.log.%d{yyyyMMddHH}" immediateFlush="false" append="false">
<PatternLayout pattern="%msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<AsyncLogger name="PublicLog" level="info" additivity="false" includeLocation="false">
<AppenderRef ref="public_log"/>
</AsyncLogger>
<AsyncLogger name="org.springframework" level="INFO"/>
<AsyncLogger name="org.apache.httpclient.wire" level="INFO"/>
<AsyncLogger name="org.apache.http" level="INFO"/>
<AsyncLogger name="org.apache.commons.httpclient" level="INFO"/>
<AsyncLogger name="org.mybatis.spring" level="INFO"/>
<AsyncLogger name="com.xiaoju" level="INFO" additivity="false" includeLocation="true">
<AppenderRef ref="INFO_FILE"/>
<AppenderRef ref="ERROR_FILE"/>
</AsyncLogger>
<AsyncLogger name="com.xiaojukeji.carrera.common.disf.EndpointManagerSD" level="WARN" additivity="false" includeLocation="false">
<AppenderRef ref="INFO_FILE"/>
<AppenderRef ref="ERROR_FILE"/>
</AsyncLogger>
<AsyncLogger name="com.xiaoju.manhattan.financing.base.metric.odin" level="WARN" additivity="false" includeLocation="true">
<AppenderRef ref="INFO_FILE"/>
<AppenderRef ref="ERROR_FILE"/>
</AsyncLogger>
<Root level="INFO" includeLocation="false">
<AppenderRef ref="INFO_FILE"/>
<AppenderRef ref="ERROR_FILE"/>
</Root>
</Loggers>
</Configuration>
2.2.cpu
cpu占用过高一般是线程阻塞等原因导致,这部分需要使用
show-busy-java-threads
去定位代码
下载
wget --no-check-certificate https://github.com/oldratlee/useful-scripts/archive/release.zip
然后可以基于命令去查找定位到线程阻塞的代码。我这里线程的Busy都是0
并且没有线程Blocked的数据,是因为现在没有进行压测。

3.JVM
JVM优化,主要是降低gc的时间,避免出现fullGC 如何查看GC的时间,具体问题百度吧
下面给出一些JVM参数的模板
8C16G:G1
java_opts="-XX:+UseG1GC -Xms8g -Xmx8g -Xss512k -XX:+PrintCommandLineFlags -Xloggc:/home/data1/logs/gc.log -XX:GCLogFileSize=300m \
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps \
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:ParallelGCThreads=8 \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/data1/logs/_heapdump"
4C8G:G1
-server -Xms4g -Xmx4g -XX:MaxNewSize=2g \
-XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=40 -XX:G1HeapRegionSize=8m \
-XX:+ExplicitGCInvokesConcurrent -XX:ParallelGCThreads=4 \
-Xloggc:/home/admin/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps \
-Dsun.rmi.dgc.server.gcInterval=2592000000 \
-Dsun.rmi.dgc.client.gcInterval=2592000000 \
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m \
-XX:ReservedCodeCacheSize=256m \
-XX:MaxDirectMemorySize=512m \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/logs \
-XX:ErrorFile=/home/admin/logs/hs_err_pid%p.log
4.tomcat调优
在并发比较高的场景下还需要优化tomcat
核心优化的参数如下几个
tomcat.max-threads tomcat.accept-count max-connections
4.优化前后对比
4.1.优化前
客户端监控

服务端监控

4.2.优化后
客户端监控

服务端监控

性能分析工具
Arthas:https://arthas.aliyun.com/doc/ 性能分析脚本(useful-scripts):https://github.com/oldratlee/useful-scripts show-busy-java-threads::https://github.com/oldratlee/useful-scripts/blob/dev-2.x/docs/java.md#-show-busy-java-threads
关于我
更多内容可关注公众号
Github: https://github.com/liangliang1259/common-notes 公众号 
文章转载自阿亮的日志,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




