暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

极致性能优化指南(一)

阿亮的日志 2021-06-16
634

前言

最近对正在负责的一个系统做了一个压测,在此复盘了这次压测的整体流程,以及需要关注的指标,由于很多数据指标没有被保留,因此没有完全还原场景,后续再来完善吧,这篇就做入门指引吧。

概览

  • 压测指标
  • 系统优化点
  • 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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论