一次接口响应时间过长的性能分析及排查过程

政采云技术团队.png

汤圆.png

一、常见性能指标

性能测试主要是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。

在性能测试中,常见的性能指标有吞吐量(即每秒系统处理事务的数量,TPS)、响应时间(即从客户端请求发起到服务器响应结果的时间,RT)、资源使用率( CPU、内存使用率、磁盘 IO 读写速率、网络)。

不论是在性能测试中,还是在生产环境中,常常会遇到响应时间过长的问题。响应时间是性能评估的一个重要指标,会对最终用户产生直接影响,评估一个产品的快慢,响应时间是最直观的感受,接下来将围绕响应时间对性能测试研究展开讨论。

二、响应时间(RT)

对用户来说可以对吞吐量( TPS )、并发数不关心,但响应时间及系统稳定性却是用户感受系统性能的最直观体现。从用户角度来说,系统性能就是系统对用户操作的响应时间,接下来对响应时间的分类进行介绍。

1、响应时间( RT ):对请求作出响应所需要的时间,包括用户客户端呈现的时间、请求/响应数据网络传输时间、应用服务器处理时间以及数据库系统处理时间等,是用户感知软件性能的主要指标。

2、平均响应时间:在测试过程中,所有请求的平均耗时。

3、TOP 响应时间:对于某个接口,准确统计它的流量时非常有用,它可以取出一些偶然得到的异常值。将所有请求的响应时间先从大到小进行排序,计算指定比例的请求都是小于某个时间。该指标统计的是大多数请求的耗时,这样可以将瞬间的尖峰响应时间去掉,使统计平均更具真实意义。

  • TP90:90th 百分点是统计时所采用的最高值,超过的10% 的数据将被舍弃。
  • TP95:95th 百分点是统计时所采用的最高值,超过的 5% 的数据将被舍弃。
  • TP99:99th 百分点是统计时所采用的最高值,超过的 1% 的数据将被舍弃。

随着吞吐量的增大,响应时间会逐渐变长。当吞吐量达到峰值之后,后面堆积队列中的请求的响应时间开始急剧加大。如果仅仅关注平均值,由于大多数请求的响应时间相对较短,有少数接口可能是 10ms 级别,慢请求往往只占一个很小的比例。所以从平均值中分析数据时,慢响应的接口响应时间被平均了。但实际上,可能有超过 1%,或者 5% 请求的响应时间已经远远超出目标响应时间的范围。因此,在性能测试中,合理的指标是关注 TP95 或者 TP99 的响应时间,本接口将采用 TP99 的响应时间进行分析。

三、一次压测过程及排查分析

本次压测一个接口,主要功能是数据库多表查询。通过查询表 A 获取品牌商和代理商的映射关系,通过表 B 获取用户 id 和用户名的关联关系,判断授权是否有效,然后再反查表 A 获取到被授权的代理商。

1、压测结果与分析

在对接口进行压测时,采用阶梯加压的方式,找出最佳并发数,评估 RT 以及资源使用率的情况是否在正常范围值内,得出在该并发下的最佳 TPS。在 20 并发时,数据正常无报错,发现在 40 并发出现 0.01% 的错误率,在 60 并发时,出现大量报错,错误率达到 0.94%。此时观察平均相应时间逐渐递增且 TP99 达到约 1000ms,通过 jmeter 查看报错请求,发现加载时间(load time)达到 1000ms(正常请求 load time 在几百毫秒以内),且大量报错请求都是因为加载时间超时导致。

压测并发1.jpg

压测图片jmeter.jpg

2、排查过程

为了使应用在高并发、请求量激增的情况下也能保持稳定,针对这个压测结果,对其进行分析并解决。

具体可以从以下四个方面进行排查:

2.1、 排查 CPU 和内存

使用监控工具 PINPOINT 通过查看服务调用关系,此服务系统只调用了数据库,在并发数达到 60 高并发时,系统 CPU 使用率大多数在 80% 以内,但是响应时间却达到 1.92 秒。通过阿里云数据库监控发现数据库的 CPU 和内存使用率均在正常范围之内,由此分析出性能瓶颈出现在响应时间 RT 上。

截图1.jpg

数据库.jpg

2.2 、排查业务逻辑

当问题发生时,第一时间查看日志里面的报错信息。通过观察日志发现,在压测的时候并不是所有的请求都会报出等待连接超时的错误。将第一个报错的线程的位置找到,发现第一个报错的线程是在压测进行一段时间后才出现的。低并发没有报错,高并发开始报错,这意味着,业务代码没有逻辑上的问题。

2.3、 排查数据库索引和数据量的情况

  • 数据量:经查询,存放数据表中的数据量达到 1000 条,处于正常范围之内,不存在数据量过大的问题。表1.jpg

  • 索引:根据 explain 语句查询,发现该 SQL 语句走index索引,SQL 执行时长为 43ms。

    以上结论说明本次压测结果的问题并不是表数据量过大或者是 SQL 语句的问题。

表1.1.jpg

2.4、 排查数据库连接池的情况

通过 PINPOINT 监控工具发现,MYBATIS 中 SqlSessionTemplate --> getConnection() DruidDataSource 超时,确定是druid 连接池超时问题。Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池,插件框架和 SQL 解析器组成。主要是为了扩展 JDBC 限制,可以实现统计 SQL 信息、SQL 性能收集、SQL 注入检查、SQL翻译等。

发现是数据库连接池的问题后,接下来再从 SqlSession 和连接池参数两个方向来排查。

问题图.jpg

(1、 关于 SqlSession的关闭问题

当发现数据查询超时,可检查 SqlSession.close 问题。SqlSession 是通过 SqlSessionFactory 来构造的,相当于维护一个连接池,当不停的进行查询的时候,由于没有关闭连接,导致与数据库的连接数量达到了一个上限,到达上限之后,再次请求查询时,Factory 会判断是否存在关闭空闲的的 SqlSession 供数据查询使用,此时会有一段等待时间,会导致数据查询超时。而本项目是采用 Spring 整合 MYBATIS 框架,spring 默认不执行 SqlSession.close,它通过动态代理来完成的执行了 SqlSession.close。那么本次数据库连接池的问题就不是SqlSession 导致的。

(2、 Druid连接池参数配置

本接口应用 Druid 连接池参数配置如下:

# 初始化大小,最小
spring.datasource.initialSize=1 
spring.datasource.minIdle=3
# 线程池最大线程数
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000                                                
复制代码
  • initialSize: 初始化时建立物理连接的个数,初始化发生在显示调用 init 方法,或者第一次 getConnection() 时。

  • minIdle: 最多维持多少个空闲连接,即使客户端没有需求,也要至少维持多少个空闲连接,以应对客户端的突发需求。

  • maxWait: 连接最大等待时长。maxWait 参数表示从连接池获取连接的超时等待时间,单位 ms。获取连接等待的直接原因是池子里没有可用连接,包括连接池未初始化,连接长久未使用已被释放,连接使用中需要新建连接,或连接池已耗尽需等待连接用完后归还等。

  • maxActive: 连接池中线程的最大连接数。

连接超时的问题可能由 Druid 连接池参数 maxActive、maxWait 配置大小引起的。

四、压测验证

介于以上结论,接下来将对数据库连接池参数设置进行压测验证。

通过修改数据库连接池的配置:(压测前配置为 maxActive = 20,maxWait = 60000ms)

本次压测验证通过设置 maxActive 和 maxWait 的不同值来查看设置的大小不同对压测结果的影响:以下是将 maxActive 和 maxWait 按递增的方式设置数据,在并发 20 和并发 60 的两种场景下进行压测的结果。

下面将分析 maxWait 参数大小对压测结果的影响,将 maxActive 设置为 20(压测前配置),将 maxWait 分别设置为 1000ms、9000ms、60000ms,在 60 并发下,观察性能指标吞吐量 TPS、平均响应时间RT以及错误率变化。发现调大 maxWait 值,在 60 高并发下仍然报错,TP99 达到 1000ms 以上,存在超时请求,错误率达到 3.29%,由此可排除 maxWait 参数问题。

maxWait.jpg

接下来对 maxActive 大小调参进行压测验证,在 60 并发下,将 maxWait 设置为 60000ms(压测前配置),将 maxActive 的大小分别设置为 20、60、100,观察其吞吐量 TPS、平均响应时间 RT 以及错误率变化。发现 maxActive 在 20、60 下均报错,且 maxActive = 60下的 TPS 低于 maxActive = 100 的情况,将 maxActive 调为 100 时,TPS 有明显的提升达到 324/sec、TP99 也保持在几百毫秒以内,无超时请求,且错误率为 0。再继续调大 maxActive 的值为 200 发现出现大量的请求超时,TP99 达到 7.6%,TPS 降低。maxWait 为60000ms 且 maxActive 为 100 时,服务器 CPU 和内存使用率、数据库 CPU 资源使用情况均正常,由此可推出将 maxActive 参数设置成 100 是最佳参数,此时该接口的压测指标全部符合预期。

maxActive.jpg

五、总结

本次就压测过程中发现响应时间过长的一次排查分析过程,在遇到压测时响应时间过长时可以从服务器 CPU 和内存、数据库 CPU 和内存、应用程序代码、数据库索引及配置等方向进行排查。

使用数据库连接池参数配置时,配置 maxWait 参数不宜太小,在请求速度大于处理速度的情况下等待队列会越排越长,最终业务上的表现就是业务接口大量超时,流量越大造成实际吞吐量反而越低。配置 maxActive 参数不宜太大,虽然配置大了看起来业务流量飙升后还能处理更多的请求,但切换到 DB 视角会发现其实连接数的增多在很多场景下反而会减低吞吐量, 在本项目中,随着业务流量的增加,该接口的并发量接近于 100,将 maxActive 配置为 100 时,在高并发下没有报错,因此,在数据库连接池配置的设置中,一般将maxActive 设置成可能的并发量,根据具体业务和场景设定。

推荐阅读

MySQL 之 innodb 自增锁原理实现

基于父子关系的高效去重算法

分布式一致性

Lucene 查询原理解析

招贤纳士

政采云技术团队(Zero),一个富有激情、创造力和执行力的团队,Base 在风景如画的杭州。团队现有300多名研发小伙伴,既有来自阿里、华为、网易的“老”兵,也有来自浙大、中科大、杭电等校的新人。团队在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 [email protected]

微信公众号

文章同步发布,政采云技术团队公众号,欢迎关注

政采云技术团队.png

猜你喜欢

转载自juejin.im/post/7108873657589432328
今日推荐