性能压测总结

        最近公司上了一个大项目,在上线前进行了3周的全链路压测,总结了不少优化点,这里列举一些,以供大家参考

        1、统一日志处理的aop拦截冗余

                在拦截aop时pointCut配置,将controller和service层都做了切入,导致很多地方的日志造成了冗余打印,再加上重复的aop拦截也很耗时,最终移除所有的主动拦截,pointCut只配置了一个注解,在需要日志的地方,主动添加注解@AroundLog。

        2、log.info耗时比较严重

                我们已经配置了异步发送log,但是还是由于打的日志过多,导致了写磁盘加锁严重,但是又不能一行日志都不加,无法定位生产问题的,而且日志的打印都采用了json化。最终的改动方案就是移除json化,只打印对象,对于出参较多的接口,只打印核心的几个出参

        3、数据库写操作过慢

                这个问题是由于mybatis的generator配置不对,导致自动生成的insert语句为了返回自增id,在sql前面先进行了一次查询操作,最终改为了配置useGeneratedKeys="true" keyProperty="id" keyColumn="id"这三个参数来返回。

        4、代码调用冗余

                这个是微服务的一个弊端,比如一个最基础的服务,查询商品信息,基本上其他所有的服务都会调用,如果商品服务本身有一些慢的话,每一个服务调一遍,链路稍微长一些的服务可能就会被拖垮,再加上相同数据重复查询,造成了商品服务压力过大

                但这个又好似误解,微服务本来就是各自处理各自的业务,尽量避免了参数间相互依赖,所以针对该问题,我们也只是尽量做到了某些参数透传,来解决该问题

        5、串行改为并行/异步执行

                有些接口需要调用10+个外部服务,这些服务本身又不相互依赖,所以可以采用并行的方式,我们是采用了jdk自带的CompletableFuture实现了并行调用

                另外也存在非主流程业务较慢,将其移入了异步方法调用中实现,比如发MQ,将同步发送改为异步发送。

        6、并行/异步使用姿势不正确

                这个接上条。在刚开始使用CompletableFuture时,由于对该工具的理解不够,导致代码是如下写法:

CompletableFuture<Void> aFuture = CompletableFuture.supplyAsync(
  () -> queryFromA();,
  ExecutePool.getInstance().getExecutor()
);
// 获取异步线程结果
ThreadsUtils.completableFutureGet(aFuture);
queryFromB();

                这里的问题是,当使用get方法时,其实是阻断了主线程,直到future里的全部线程执行完成,才能拿到数据,然后再执行下面那个方法,造成了主线程的时间浪费。这里是我的理解错误导致的,其实future在生成的时候,里面的线程已经开始跑了,所以如果这个时候主线程还想干点什么事情,应该先去做,然后在调用get方法获取future的值。所以这里需要将queryFromB()方法移到get方法前面即可。

               在使用异步的时候,也踩了一个坑,使用spring的@Async注解实现异步时,其实效果和我们所了解的事务失效的概念一样,这个异步不能放在主方法的同一个类中,需要另起一个类调用才可以。这个是在查看日志时发现异步的线程ThreadName竟然依然是主线程name,才发现使用姿势不对的。

        7、禁用BeanUtils.copy()方法

               该方法耗时严重,具体原因就不列举了。经过分析,最终采用了mapstruct工具实现了bean之间的复制工作

        8、线程池优化

               这个不光指的是异步线程池,也指tomcat线程池和数据库线程池的优化,当然,我们为了提升性能,采用了undertow做为java容器,数据库线程池采用了hikari。具体的优化参数就不列了,因为毕竟不同的项目,环境不一样。

        9、对下游接口的缓存

               这个需要针对实际情况做出判断了,如果下游数据的短时间不一致对业务没有影响或者影响不大,可以考虑采用缓存来提高RT

        10、对非核心业务进行降级

                这个被同事成为压测作弊^_^。因为我们有一个服务调用了3个外部服务,都非常慢,但是这三个服务其实不调用也不影响使用,如优惠券服务,双十一的时候如果屏蔽该接口,并不影响用户购买商品,但是极大的提高了RT,所以我们对这些服务做了开关,在流量高的时候,屏蔽这些接口,保证接口的高响应

        11、本地压测调试

                这个其实不叫性能优化,只是推荐个方法。刚开始的时候,是跟着团队在压测,只有轮到自己服务的时候才可以压,时间比较紧张,很多问题定位不到。我就自己在本地装了jmeter和arthas,自己压测自己分析,虽然时间上肯定会比服务器上慢,但是一些链路问题,高耗时接口还是可以定位到的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章