孙 立 哲
(公安部第三研究所eID事业部 上海 201204)
随着计算机网络的快速发展,网络用户数增多,并发访问量加大,分布式应用系统在高并发可用性方面面临巨大的挑战。为了提高系统的高并发性能,分布式应用系统内部设计多采用异步处理模式。随着互联网应用技术复杂性不断提高,高效的测试技术和工具逐渐成为高质量应用的必要保证。
HTTP接口即基于HTTP协议、可远程访问的接口,是分布式应用系统[1]的一种技术实现。HTTP协议是互联网上客户端浏览器或其他程序与Web服务器之间的应用层通信协议[2]。接口是预先定义的函数,旨在提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力。接口内部实现对特定业务处理逻辑的封装,接口调用方只需按接口调用规则进行访问即可完成特定业务的处理,无需关注内部实现细节。
根据接口内部业务处理模式不同,HTTP接口可分为同步接口和异步接口。同步接口是指请求方以HTTP请求方式访问服务端HTTP接口,接口收到请求并完成全部业务处理后将结果以HTTP响应方式直接返回给请求方。异步接口是指请求方以HTTP请求方式访问服务端HTTP异步接口,请求参数中需包含一个用于接收异步处理结果的HTTP回调接口地址,接口收到请求并在完成部分业务处理后以HTTP响应方式将处理结果返回给请求方(即同步返回),或者不做任何业务处理直接以HTTP响应方式返回一定数据以告知请求已收到,之后HTTP接口内部再启动新线程处理后续业务并访问请求方提供的回调接口将结果发给请求方(即异步返回)。HTTP异步接口业务流程图如图1所示。
图1 HTTP异步接口的业务处理流程图
JMeter[3]是Apache组织开发的基于Java的压力测试工具,以其开源、小巧以及功能强大等优势而备受青睐[4]。它可用于对服务器、网络或对象模拟巨大的负载,在不同压力类别下测试它们的强度及分析整体性能。JMeter支持对Web服务HTTP接口的性能压测[5],但其在HTTP异步接口的性能压测方面存在一定的局限性。JMeter对HTTP接口的压测只能覆盖到同步接口和异步接口的同步处理逻辑,无法覆盖到异步接口内部的异步处理逻辑。单独使用JMeter对HTTP异步接口进行的性能压测不能覆盖接口内部完整业务处理逻辑,因此JMeter的压测结果不能反映出接口自身的真实性能情况。
本文根据HTTP异步接口内部业务实现特性,结合JMeter支持纯Java脚本编写的特点,设计了一套集JMeter工具、MySQL数据库表设计[6]、模拟接口测试桩设计以及自定义Java脚本设计等为一体的性能测试方案。该方案能够覆盖HTTP异步接口完整业务处理逻辑,且通过在真实产品中进行性能压测实践,证明了该方案的可行性与实效性,弥补了JMeter在异步接口性能压测中所表现出的不足。
性能测试方案的整体思路及具体实现按整个压测过程可分为压测前准备、JMeter压测与数据收集以及结果统计分析三部分。
本性能测试方案所需测试环境主要涉及JMeter客户机、被压测接口所在服务器、模拟回调接口测试桩所在JBoss服务器、MySQL数据库服务器。性能测试环境整体架构如图2所示。
图2 性能测试环境整体架构图
压测前准备主要完成MySQL数据库服务搭建与数据库表设计、模拟接口调用方的HTTP回调接口测试桩设计与实现及基于JBoss服务的部署、被压测接口作特定处理,以及各服务器和JMeter所在客户机环境性能调优。
搭建MySQL服务器,创建数据库,设计数据表[7]。针对单级HTTP异步接口,即接口内部不调用其他异步接口,只需设计两个数据表即可。一个为请求表,用于记录被压测HTTP接口收到的请求数据,一个为响应表,用于记录被压测接口异步响应数据。表字段设计分别见表1和表2。
表1 请求表
表2 响应表
针对二级HTTP异步接口,即接口内部又调用其他异步接口,需作扩展设计,即设计四个数据表。其中:三个请求表依次分别记录被压测HTTP接口收到的请求数据、被压测接口内部调用其他异步接口时下发的HTTP请求数据、被压测接口的回调接口收到的HTTP请求数据;一个响应表记录被压测接口的回调接口返回的异步响应数据。针对多级HTTP异步接口,可按上述逻辑继续作扩展设计。
被压测接口在接口内部增加两部分特定业务处理。一是在请求处理开始之前将请求串插入MySQL库请求表,二是将异步返回的响应数据按要求插入MySQL库响应表。增加特定业务处理后的流程图如图3所示。
图3 HTTP异步接口性能测试特有业务流程图
搭建JBoss服务器,使用Java脚本基于Web Servlet技术[8]开发模拟请求方的HTTP回调接口的测试桩并打包成Web存档文件部署在JBoss服务上。测试桩接口内部业务逻辑为接收被压测接口异步返回的数据并按预定要求作出响应。为确保各服务器之间有良好的通信性能,需设定各测试用服务器在硬件与操作系统等配置方面与被压测接口所在服务器保持一致,MySQL数据库服务和JBoss服务在线程池、日志等级等方面作性能最优配置。整套测试环境在同一局域网内。
使用JMeter合理设计测试计划,对HTTP异步接口进行压测并在压测过程中收集接口请求数据和异步返回的响应数据:1) 在JMeter测试计划中,针对被压测接口新建一线程组,在线程组中添加取样器“HTTP请求”,并配置接口请求地址、请求方式及请求参数等数据。2) 使用JMeter配置元件“用户定义的变量”定义请求串中可配且有可能需手动调整的参数,如数据库配置信息等。使用JMeter配置元件“CSV Data Set Config”读取需要从数据库中提取的批量测试数据,在此之前需编写自定义Java脚本实现从数据库中提取批量数据并生成测试所需逗号分隔值(Comma-Separated Values,CSV)数据文件。3) 在JMeter前置处理器“BeanShell PreProcessor”中编写Java脚本,调用事先用Java脚本编写并打包好的自定义Jar包,实现对请求参数的特定处理,如对某请求参数数据加密或作签名等。4) 使用JMeter断言“响应断言”判断被压测接口同步返回的响应数据是否正确。5) 使用JMeter监听器“察看结果树”检查短时间高并发下异常信息,在长时间高并发下需禁用“察看结果树”以确保JMeter自身性能良好。6) 使用JMeter监听器“聚合报告”记录并显示压测结果。
根据实际性能需求,在线程组的线程属性和调度器配置中分别配置并发用户数和压测持续时间,启动JMeter压测。JMeter压测过程中,将被压测接口的请求数据和异步返回的响应数据分别插入MySQL数据库请求表和响应表中。
对JMeter压测结果以及压测过程中收集的请求数据和响应数据作统计分析:1) 通过分析JMeter聚合报告结果,可评估异步接口中同步处理业务的性能。2) 采用自定义Java脚本对MySQL库请求表和响应表中的数据作统计分析,评估HTTP异步接口内部完整业务的性能。
具体分析步骤:1) 比对请求表中记录数和响应表中记录数是否一致,若不一致,则说明有失败的请求,若一致则继续后续比对分析。2) 逐条读取请求表中的记录,根据业务流水号字段值到响应表中去查找对应记录。若能找到,则继续检查响应数据是否正确,若正确则本次HTTP请求处理成功,若不正确则本次请求失败。若根据业务流水号未能在响应表中查找到对应记录,则本次HTTP请求失败。3) 在逐条读取请求表中记录并作比对分析的过程中,统计记录HTTP请求成功总数和失败总数。若HTTP请求成功总数与请求表中记录总数相等,则说明HTTP异步接口在高并发压力下均能成功处理各HTTP请求。若不等,用请求失败总数除以总请求数得到出错率。4) 针对请求成功的记录,根据响应表中记录的业务处理时间与请求表中对应记录的业务处理时间计算本次HTTP请求的处理耗时。统计所有成功的请求中的最大响应耗时、最小响应耗时和平均响应耗时。
某身份标识产品对外提供的短信服务(Short Messaging Service,SMS)签名接口是一个复杂的二级异步调用接口,其向第三方服务提供的回调接口也是异步接口。SMS签名接口及其回调接口相关的完整业务流程如图4所示。
图4 SMS签名接口完整业务处理流程图
SMS签名业务完整处理逻辑分两个阶段,第一阶段为从请求方向SMS签名接口发送请求开始到SMS签名接口向第三方服务下发短信下行(以下简称“MT”)请求为止,第二阶段为从第三方服务向MO回调接口发送请求开始到短信上行(以下简称“MO”)回调接口向请求方发送异步处理结果为止。
根据性能测试方案中所述针对二级异步调用接口的数据库表设计方法,在MySQL数据库中新建四个表,分别为SMS签名请求表、SMS签名短信下行请求表、SMS签名短信上行请求表、SMS签名响应表。各请求表字段同表1,响应表字段同表2,四个表中的记录通过业务流水号字段唯一关联。SMS签名请求表记录SMS签名接口的HTTP请求数据,SMS签名短信下行请求表记录SMS签名接口内部下发的MT请求数据,SMS签名短信上行请求表记录MO回调接口的HTTP请求数据,SMS签名响应表记录MO回调接口内部下发的SMS签名回调请求数据,即SMS签名接口返回的异步响应数据。SMS签名请求表和SMS签名短信上行请求表可由被压测接口进行数据插入,也可由请求发起方进行数据插入。由请求发起方进行数据插入,可将请求发起方与被压测接口之间的网络传输、Web服务等相关环境性能情况涵盖在内,得出的性能评估结果也更全面,因此,本文采取由请求发起方进行数据插入的方式。被压测的SMS签名接口和MO回调接口内部分别增加特定处理逻辑,即SMS签名接口中在下发MT消息前将即将下发的MT请求数据插入SMS签名短信下行请求表,MO回调接口中在下发HTTP请求给请求方回调接口前将HTTP请求数据插入SMS签名响应表。按请求方回调接口规则开发模拟测试桩供MO回调接口调用。
由于SMS签名接口是二级异步调用接口,业务逻辑较复杂,因此,需要在前述性能测试方案基础上做一定的延伸扩展。在同一个测试计划的同一个线程组内创建两个HTTP请求取样器,分别对应SMS签名接口和MO回调接口。SMS签名接口取样器内部的BeanShell前置处理器脚本中需增加将HTTP请求数据插入SMS签名请求表。MO回调接口取样器内部的BeanShell前置处理器脚本中需增加将HTTP请求数据插入SMS签名短信上行请求表。编写Java脚本用软实现方式模拟终端内部处理逻辑生成签名值并组装成MO回调接口请求数据,以Jar包的形式供JMeter调用。基于MO回调接口内部有对MO消息与MT消息的数据关联检查,在MO回调接口前置处理器脚本中还需增加一层逻辑处理,即只有在SMS签名短信下行请求表中查找到对应的记录后才下发MO回调请求。根据产品实际性能需求,配置200个并发用户数,循环100次,执行JMeter压测。
采用性能测试方案中所述结果统计分析方法,对在压测过程中插入MySQL数据库四个表中的数据做扩展性统计分析,评估SMS签名接口和MO回调接口内部完整业务逻辑性能情况。编写自定义Java脚本,逐一提取SMS签名请求表中记录,在SMS签名响应表中进行查找,检查是否有对应的响应串并对响应串数据正确性作判断。对于能找到对应响应串且响应串数据正确的记为请求成功,对于未找到或者找到但相应数据不正确者记为请求失败,记录请求成功总数和失败总数。对于请求成功的记录,根据SMS签名请求表和SMS签名短信下行请求表中的业务处理时间字段数据,按前述统计方式统计第一阶段SMS签名接口内部完整业务逻辑处理平均耗时,根据SMS签名短信上行请求表和SMS签名响应表中的业务处理时间字段数据,统计第二阶段MO回调接口内部完整业务逻辑处理平均耗时,记录第一阶段耗时、第二阶段耗时以及两个阶段的总耗时,统计分析所有请求成功的记录的平均响应耗时、最大响应耗时和最小响应耗时。对于请求失败的记录,记录相应的业务流水号,便于作后续的问题排查分析。以上统计所得数据全部记入文件备查。
压测生成的JMeter聚合报告显示:SMS签名接口总请求数为20 000,内部同步处理逻辑平均响应耗时为297毫秒,最小响应耗时为48毫秒,出错率为0.00%;MO回调接口总请求数为20 000,内部同步处理逻辑平均响应耗时为1 267毫秒,最小响应耗时为90毫秒,出错率为0.00%。两个接口内部同步处理逻辑性能尚在可接受范围内。
对JMeter压测过程中插入数据库表中的各请求数据和响应数据作统计分析。JMeter发给SMS签名接口的总请求数为20 000,发给MO回调接口的总请求数为20 000。异步收到结果的总记录数为20 000,且所有记录的响应数据均正确。其中,能与请求相关联的有19 896条记录,无法关联的有104条。能与请求相关联的所有记录中,最小响应耗时50 394毫秒,最大响应耗时56 522毫秒,平均响应耗时51 270毫秒。
对结果作进一步分析,从发给MO回调接口的总请求数以及接口对应的后台日志可以确认,MO回调接口的20 000次请求中有104次未能成功返回异步结果,错误率为0.52%。通过比对JMeter发出请求的时间与接口对应后台日志中显示的收到HTTP请求的时间,发现服务端接口收到请求的时间比JMeter发出请求的时间滞后约25秒。统计分析生成的部分结果示例如图5所示。
图5 统计分析生成的部分结果示例
综上,基于本文提出的性能测试方案,不仅使用JMeter完成了对SMS签名异步接口和MO回调异步接口内部的同步业务逻辑的性能评测,还根据压测过程中收集的数据及对数据的统计分析完成了对两个异步接口内完整业务逻辑的性能评测,发现了仅仅使用JMeter压测无法检出的两个性能问题。实践证明,本文所描述的性能测试方案切实可行且有明显实效。
本文结合异步接口内部处理逻辑,从分层压测和统计分析的角度出发,整合JMeter性能测试计划设计、MySQL数据库表设计、模拟接口测试桩设计和自定义Java脚本设计等多方面的技术,设计了一套能够覆盖HTTP异步接口内部完整处理逻辑的性能测试方案。通过在真实产品中进行性能压测实践,证明了该方案在HTTP异步接口性能评测方面的可行性与实效性。基于分层压测和统计分析的特性,该方案具有良好的可扩展性,不仅适用于具有二级异步调用关系的接口性能评测,也可以通过延伸扩展应用于具有多级异步调用关系的复杂接口性能评测。