压测调优.md - liuxiang/liuxiang.github.io GitHub Wiki

一.瓶颈 & 优化

1.瓶颈

# 硬件
CPU   : top检查占位在总算力的80%较为合理
Memry : 观察jvm堆内(jvisualvm)/堆外(free)的内存使用情况.
disk  : 关注容量与性能.
网络句柄: 关注连接句柄(netstat),避免长连接(Keep-Alive)失效.

# 网络
试压端网络上行(外发): 因小于路由器硬件带宽
服务端网络下行(接收): 因小于路由器硬件带宽

# 软件
算力损耗: 切片`核心处理`与`逻辑包裹`两者tps情况,评估应用损耗合理性.
内存滥用: 观察内存的回收频次及耗时(暂没有评估好坏的参考量).发现创建回收高频对象,考虑将其优化(尝试逻辑避免).
通道屏障: nginx连接配置; tomcat中http连接数; DB连接数; RPC(dubbo)连接数; 代码中线程池,信号量等屏障;

2.优化

# 运维优化
硬件表现评估: 是否达到资源利用率,未达到则需检查通道屏障情况.
通道屏障疏通: 流量穿透顺序的各屏障是否到达合理值.
高性能存储替换: 针对io性能的硬件优化.

# 代码优化
内存 换 磁盘: 热区数据内存化.必要时还可考虑多级缓存. (本地内存 > 分布式内存)
异步 换 同步: 对可异步化内容独立异步化,不消耗串行业务的rt与cpu. (外部异步(kafka) > 本地异步)
避免一切停顿: 日志或监控过程中屏障信息,在资源允许的情况下,尽量避免一切停顿(锁停顿;自旋停顿;队列停顿;BIO;)
减少对象拷贝: 减轻gc压力同时又能节省cpu的算力. 目标零拷贝

3.监控

# 代码埋点
Grafana + promethes/influxDB: 观察目标服务的tps,rt. 目标机器的各硬件指标.

# jvm监控
gc    情况: -Xloggc:gc.log / jvisualvm / jstat -gc   (识别内存溢出风险)
thread情况: jstack / jfr / arthas										 (识别线程溢出风险)

# 其它
网络句柄: 关注连接句柄(netstat),避免长连接(Keep-Alive)失效.

Idea - Profiler分析工具

详见-官方教程: https://www.jetbrains.com/help/idea/cpu-profiler.html https://blog.jetbrains.com/idea/2020/03/profiling-tools-and-intellij-idea-ultimate/

  • Cpu and Memory Live Charts

CPU Profiler/Allocation Profiler/Java Flight Recorder CPU事件探查器/分配事件探查器/ Java飞行记录器

  • CPU Profiler

  • Java Flight Recorder
Commercial Features must be unlocked to start a Flight Recording for the target process. You can unlock the Commercial Features by invoking 'jcmd 47280 VM.unlock_commercial_features'. You can also add -XX:+UnlockCommercialFeatures to the command line and restart the target process. Commercial Features are covered by the Binary Code License.
# 解锁商业功能-运行时
jpid=`pgrep -n java` && echo $jpid;\
  jcmd $jpid VM.unlock_commercial_features

# 解锁商业功能-启动前
-XX:+UnlockCommercialFeatures

二.操作指导

资源(CPU,memory,thread)相关快速诊断.md

详见: 资源(CPU,memory,thread)相关快速诊断.md

三.标准化

1.基建配置标准

组件 通道屏障 其它
nginx
mysql
redis
es
大数据套件..

2.标准java应用

  • 标准化jvm配置
# $CPU为容器可使用的CPU数上限,$MEM_75P为容器内存上限的75%,他们的获取方式如下
CPU=$(< /proc/cpuinfo grep -c processor)
MEM=$(< /proc/meminfo grep MemTotal|awk '{printf "%d", $2/1024/1024 }')
MEM_75P=$(echo "${MEM}"|awk '{printf "%d", $1*1024*0.75 }')

# 固化参数
-XX:+PrintJNIGCStalls -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -XX:+PrintGCApplicationStoppedTime
-XX:+HeapDumpOnOutOfMemoryError -Xloggc:$APP_OUTPUT/logs/gc.log -XX:HeapDumpPath=$APP_OUTPUT
-Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8
-Djava.net.preferIPv4Addresses -DdisableIntlRMIStatTask=true
-Dcom.sun.management.jmxremote -XX:+PrintGCDateStamps -XX:+PrintGCDetails
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=10055
-Djava.rmi.server.hostname=$LOCALIP

# 可变参数
-server -XX:MaxMetaspaceSize=256m -Xss256k -XX:+UseG1GC -XX:MaxGCPauseMillis=100
-XX:G1ReservePercent=10 -XX:InitiatingHeapOccupancyPercent=30 -XX:ConcGCThreads=$CPU
-XX:ParallelGCThreads=$CPU -Djava.util.concurrent.ForkJoinPool.common.parallelism=$CPU
-Xmx${MEM_75P}m -Xms${MEM_75P}m
  • application.properties (临时)
# Spring boot内置tomcat
server.tomcat.accept-count: 等待队列长度,默认100
server.tomcat.max-connections: 最大可被连接数,默认10000
server.tomcat.max-threads: 最大工作线程数,默认200
server.tomcat.min-spare-threads: 最小工作线程数,默认10

# 编码
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true

# webService
spring.mvc.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.default-property-inclusion=non_null

# hikari连接池
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30001
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800001
spring.datasource.hikari.connection-timeout=30002
spring.datasource.hikari.connection-test-query=SELECT 1

# Tomcat应用中可默认tomcat连接池.
spring.datasource.tomcat.max-active=20
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.validation-query=select 1
spring.datasource.tomcat.default-auto-commit=false
spring.datasource.tomcat.min-idle=15
spring.datasource.tomcat.initial-size=15