性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短。压测也是检验一个架构设计是否合理的一个重要方法。
这个项目是一个线下支付的交易系统,使用线下设备发起支付。项目使用SpringMVC+Dubbo的微服务开发模式,其中SpringMvc做为Web端部署在tomcat上对外提供rest服务,其余模块使用dubbo开发,SpringMVC调用dubbo服务完成业务功能。mysql
这一次的性能优化,目的是在不调整业务逻辑的状况下经过压力测试的方式测试下单时接口的性能能达到多少,若是有性能问题,就要在不修改业务逻辑的状况下经过优化各项参数的方式(包括JVM优化、数据库链接数和Dubbo链接数)来提高总体性能。git
压力测试策略sql
采用按部就班的方式,逐渐增长并发量的方式,先以1个并发开始,慢慢增长,当达到瓶颈的时候就进行参数调整和优化。数据库
创建压测分支tomcat
压测优化过程当中,可能随时须要调整配置参数,可能会对一些配置参数进行修改或者对公共代码进行优化。为了避免让其余研发人员的开发受到干扰,在git上基于release分支创建了feature_stress分支,专门用来压测过程当中,参数配置调优使用,不影响其余研发人员的开发。性能优化
搭建压测环境服务器
为了避免不影响研发和测试人员的工做,单独申请了三台4C32G的虚拟机进行压力测试,一台部署tomcat,一台部署dubbo服务,一台部署mysql。为何只申请单机部署的方式压测呢?由于本次测试的目的是看单台服务器的性能状况,优化的目的是将单台服务器的性能最大化。多线程
准备测试脚本架构
本次测试选用jmeter做为测试工具进行压力测试,由测试人员模拟线下支付的流程写好测试脚本。并发
很保守的,从1个并发开始压测,测试结果让人很是的惊喜,压测开始几分钟后,就出现大量的链接失败,没法继续测试。出现大量的内存溢出的异常。没出现异常时的吞吐量达到了1req/s。同时,经过jconsole控制台监控tomcat,发现其线程数最高到了2万多个。
问题分析
这个异常是建立本地线程失败抛出的异常,为何有这么大量的线程呢?不合常理呀!因而查看对应的代码,原来这是一个自定义的一我的日志Appender,在这个Appender里使用了线程池,这个Appender原本的目的是使用多线程提高日志性能,而且将全部的日志都收集到一个文件中。代码相似以下:
log4j.properties中直接将新的Appender添加到了rootLogger下:
经过以上代码和日志配置文件就能看出来,每第二天志输出都会建立线程,这就是线程为何愈来愈多,最后致使没法建立新的本地线程的缘由。
为了避免影响现有的功能,将LogAppender类append方法中的线程池建立的部分变成了类的属性,并固定只用8个线程:
提交代码从新部署压测环境,再进行压测,吞吐量立刻就上来了,达到了1700req/s,
][7]
通过上面的优化以后,总体的性能还不是很高,通过jconsole监控发现,线程数仍是很高,虽然没有2万那么多了,但仍是有3000多的线程,这么多的线程根本没法发挥机器的性能,时间都浪费在线程切换上了,经过查看线程栈发现大量的线程都是dubbo链接的线程,为何如此之多呢?查看dubbo的配置文件,consumer的连接数都设置成了1000,因而将全部dubbo的consumer链接数均改成了64。同时将log4j.properties中配置了控制台输出的都关闭了。
最终的优化后的测试结果,最高达到了2600req/s。
性能优化须要从几个方面考虑:
———— / END / ————