第一次性能调优的经历

Posted by AlstonWilliams on February 17, 2019

这两天,好不容易写完了全部的API.基本上做的差不多的.

于是乎,想看看到底会不会因为高并发而造成接口崩溃.就用JMeter测试了一下.

先测试最简单的一个获取用户相关信息的接口.因为是第一次测试,我就从小并发到大并发逐渐测试.先测试20个并发的情况.没想到,一测试,就出问题了.

下面是我们测试完20个并发访问的结果:

我从右下角的Average处,我们可以看到平均执行时间为3103毫秒,也就是3秒.从每个测试记录来看,我们能看到,其中有的记录,需要的时间甚至都超过了5秒.

调用一次接口需要这么长的时间,这就有点问题了.于是,我们打开Hibernate的统计功能,来查看每个操作需要的时间.

上面的那张图片,是我在进行另一次操作的时候,截取到的图片.从中我们可以看到,获取JDBC Connection这个过程,花费了最多的时间,为36秒.而其他的就相对比较短了.

通过对比所有操作的时间,我们发现,每一次查询请求,都需要用至少1秒的时间,来获取JDBC Connection.

看到需要这么长的时间,来获取JDBC Connection.这时候,我初步怀疑是没有设置连接池导致的.我们打开MySQL的日志功能后,观察到如下结果:

从中我们可以看到,确实有大量的建立连接的操作.

这就奇怪了.我记得以前在哪看见过,说即使不自己设置连接池,Spring Boot也会自己设置一个连接池,然而,现在却并没有.

查阅其他的资料发现,如果使用的是Spring-boot-starter-jdbc来读取数据,确实会自动给建立一个连接.然而,我使用的是Spring-boot-starter-data-jpa包来读取的数据,也没有设置连接池.所以,每次查询请求,都会建立一个JDBC Connection.

明白了这个之后,就加上了HikariCP这个连接池.然后,重新构建工程,新的测试结果如下:

现在平均时间减少到了1.8秒.

建立JDBC Connnection的时间,减少到了45毫秒.

MySQL日志中,也没有建立JDBC Connection的操作了.

通过加入一个连接池,我们将接口访问的平均时间减少了一半.

其实,1.8秒仍然是很慢的.我们还有很多其他的优化策略,比如代码层面的优化,比如引入Hibernate缓存,Redis或者Memcached缓存,以及对HikariCP设置合适的参数.