07丨性能测试工具:如何录制脚本?
对于一个性能测试工具来说,如果能实现以下几大功能,那么就基本上就满足了性能测试工具的功能。
- 录制或编写脚本功能
- 参数化功能
- 关联功能
- 场景功能
- 报告生成功能
但是除此以外,在工作的细节上还有更多要求,就要看工具的实施能力了。
有很多性能测试工程师希望工具能做得非常全面,又人性化,而纵观当前的性能工具,真正能够做到傻瓜式录制完脚本,自动设置好参数化、关联、场景,直接产出结果的工具是没有的。不管是云性能测试平台,还是分布式性能测试工具(当然性能测试工具几乎全部具有分布式能力),都需要性能测试人员来定义参数化数据、设置关联、配置场景。
因此,在性能测试的过程中,对工具的配置就成为了性能测试工程师的基本能力。
今天,我们就来看下在性能测试工具中,如何录制脚本。今天的文章有些特殊,可能是专栏中少有的,有详细操作的文章。
性能工具的脚本能力
性能测试工具的脚本编写能力分为两类,一个是录制,另一个是手工编写。
现在市场上的性能测试工具虽然支持录制功能,但大部分也只是支持HTTP协议。在我们熟知的工具中,也只有LoadRunner支持更多协议的录制能力。不过幸好,现在我们所面对的应用大部分是HTTP协议的应用。
对手工编写脚本的部分,因为大部分都取决于业务场景,所以很难提出共性。如果有人提出针对性的场景,我们再做相应的示例就行。
因此今天的文章将着重讲一下测试工具的录制功能。很多人以为性能工具录制功能非常简单,点几下就能生成一个脚本,但是录制完之后,针对脚本的增强完善就做得非常少了。事实上,针对脚本,我们不仅要录制下来,还要了解录制的原理和录制完之后的脚本增强。不然,在场景中还是会遇到各种各样的问题。
性能工具中的录制功能
录制功能从原理上来说,分成两种:
- 本地录制:通过截取并解析与服务器的交互协议包,生成脚本文件。比如说LoadRunner调起IE的时候,不用修改IE的代理设置,就可以直接抓取HTTP包,并通过自己的解析器解析成脚本。
- 代理录制:通过代理服务器设置,转发客户端和服务器的交互协议包,生成脚本文件。JMeter中的脚本录制功能就是这样做的。
这两者的不同点主要在于操作上。本地录制相对简单,但有些场景受限,比如说操作只能在某台服务器上,但是这台服务器又不允许安装工具;代理录制操作复杂一些,但可以满足更多的场景。
通过这张图,我们可以简单看到代理录制的逻辑:
- 我们在IP为2.2.2.2上的主机上,打开一个代理程序,开81端口,所有到81端口的都转发到1.1.1.1的80端口。
- 当3.3.3.3主机要访问1.1.1.1的的80端口,可以通过访问2.2.2.2的81端口进行转发。
这里需要你注意的是,代理是用来转发数据包的,并不是重定向哦。不管是在本机用代理,还是远程用代理,这个逻辑都是不会变的。
有了这个逻辑之后,你要明白的一点是,客户机不一定要和代理服务器在同一台机器上。
为什么要强调这一点呢?因为有很多人用工具来录制时,都不知道这个逻辑,只知道工具是那么操作的。这也是很多人不能理解Port mapping的原因。
不同的工具录制方式略有不同。今天我们用常见的两个性能测试工具LoadRunner和JMeter做为示例工具。
JMeter的录制功能
首先打开JMeter,添加一个线程组,再添加一个HTTP(S) Test Script Recorder。界面如下:
这里有几个关键点说明一下:
- Target Controller:这里指定录制出的脚本要放到哪里去。如果你想把不同的脚本放到不同的线程组中去,在录制的时候就可以拆分开。
- Grouping:分组,这个分组功能很实用。但是如何分组就和具体的目标相关了,这一点下面我们再细说。
点击start按钮时,会提示创建一个根CA证书。这个证书生成在bin目录中,文件名是:ApacheJMeterTemporaryRootCA.crt,七天有效期。这个证书将被用来客户端转发HTTPS的请求。与此同时,还有另一个证书在同目录中生成,名字是proxyserver.jks,这是JMeter自己生成的根证书。
前面我们说到了,JMeter是用代理的方式来录制的。如果服务端用了SSL证书,在代理时也要加SSL证书,那么代理录制的结构就会变成这样。
上面的SSL证书就是用来处理上图中蓝色的这一部分。
我们点击ok之后,就会出现这个界面。在这个界面中,只有两个配置项。
- Prefix:请求名的前缀。
- Create new transaction after request(ms):一个请求完成之后,如果下一个请求超出了这里设置的时间间隔,就创建一个新的事务。
然后到主机上设置代理。
注意,这里我要敲黑板了呀:这里的代理设置,是在需要访问的客户机上。这个客户机,不一定是压力机所在的机器。这里的localhost,也应该设置的是代理服务所在的主机IP。
请注意,如果你要设置为录制HTTPS,还需要做如下两步。
第一步是,浏览器代理要把Secure Web Proxy(HTTPS)选择上,同时填上相应的代理IP和端口,下图是macOS上的图示。
但你会发现,这时仍然录制不了HTTPS应用,访问时会出现如下提示:
这时就要在客户端机器上导入上面提到的ApacheJMeterTemporaryRootCA.crt。我们打开证书管理软件,在macOS上是Keychain Access,Windows上是certmgr.msc。
这里以macOS为例。
首先打开Keychain Access。
点击上图中的Import Items。选择ApacheJMeterTemporaryRootCA.crt,导入之后选择证书。会看到如下提示:
因为这个证书不在系统信任的默认列表里,所以会提示证书不可信。
另外这里我可以再多说一句,你注意的是,全球的可信任的根证书都是默认添加到系统中的,如果你在访问网站时,提示你要安装什么证书,一定要明确知道证书是从哪来的,不要随意安装未知来源的证书。目前国内的HTTPS覆盖度不高,仍然有大量的HTTP网页,这是需要推进的网络安全之一。
然后我们双击此证书。
改为Always Trust即可。提示如下:
这时,HTTP和HTTPS都会被录制下来。然后在客户机上打开浏览器,访问你的页面,这样就录制到脚本了。
下面我们再来说下Grouping这个功能。
Grouping的设置有如下几种,如果需要将脚本分开,先确定需要如何拆分。示例如下:
第一个选项是Do not group samples,也就是不分组。
这是很多人使用的默认选项,这就相当于没有事务的概念了,每个请求都会单独统计TPS和响应时间信息。
第二个选项是Add separators between groups,在组间添加分隔,就为了好看!
第三个选项是,Put each group in a new controller,每个组放一个新的控制器。这是一个Simple Controller,它的作用也是只有一个:就为了好看!
因为脚本太长了,看起来不方便,所以分个组,看着清晰一些。话说回来,你们见过在JMeter中有很长脚本的吗?是不是很多人都没有见过?
第四个选项是,Put each group in a new transaction controller,将每个组放入一个新的事务控制器中。
Transaction Controller和Simple Controller的区别就是Transaction Controller会做为事务统计脚本执行的时间,而Simple controller不会。
第五个选项是Store 1st sampler for each group only,只存储每个组的第一个样本。
网上大部分都只描述了上面这句,但是请注意我这里还有一句关键的:从HTML文件获取所有内含的资源和自动重定向将开启。也就是说,虽说只记录了一个Sampler,但是资源也会下载,重定向也会开启。
我们把这个过程抓出来看一下,因为JMeter没有把这个过程显示出来。所以这里用Chrome Developer Tool抓一下看看。举例来说,我们在浏览器里只输入了一个https://www.jd.com。抓出如下结果。
在上面的图中,你可以看到,www.jd.com,第一个就是307 Internal Redirect。接着请求Document,然后下面是静态资源。在录制时,选择Store 1st sampler for each group only之后,只会录制到第一个请求,而后面这些在回放脚本时也都会访问。
在JMeter的代理录制中,还有一个界面如下:
中文界面中通常将之翻译为包含模式、排除模式。“模式”一词一加就显得格外高大上了。
通常这里都会写上正则表达式,比如说常用的一些:
由于正则是一个很大的话题,这里我们就不展开了,只要你懂正则,在这里就可以适用。
通过上面的内容,我们已经把JMeter录制的原理和操作的过程都详细地描述了一遍,关于JMeter的录制功能,就介绍到这里。
在此重点提醒你一下,录制是通过代理做的,一定要知道代理的原理,代理就是转发的功能。
承上启下的话
为什么JMeter这样的功能单一,性能又不好的性能测试工具能这么快的占领市场呢?
在我看来,工具能不能用取决于它能不能满足需要。在很多的性能测试场景中,JMeter已经够用了。因为性能压力工具只需要两条曲线:TPS和响应时间(如果出错最多就再看一下错误率曲线)。这些功能,JMeter都可以提供。
现在的性能项目中,我们要的压力其实并没有很大,并且大部分都是HTTP、TCP之类的常见协议,脚本所使用的资源并不多。一般能达到万级TPS的都很少很少,所以弄几个机器,JMeter也就够用了,再加上免费开源,何乐而不为呢?
而LoadRunner的失败之处就是价格高,更新慢。一想到HP糟蹋了LoadRunner,我就伤心落泪。
LoadRunner中的录制功能
我们都知道LoadRunner其实可以录制很多协议,这也是它前期扩展市场的很重要的功能。应该说,在录制这个功能点上,所有的性能测试工具都不如LoadRunner。并且LoadRunner在其他很多功能上都是强大的,强大到什么程度呢?就是有很多你不需要的,不常用的功能,它都具备。
很多人都知道,LoadRunner中的Vuser Generator只支持Windows。你有没有想过这是为什么?其实解释起来也简单,LoadRunner一开始是基于WinInet做的,就是Windows Internet API。后来可能是觉得WinInet太恶心了,于是换成了Windows socket。而Windows socket跟UNIX socket还是有一些小区别。
所以从历史延续下来,Vuser Gnenerator就一直在Windows上了。
为什么不做UNIX的版本呢?其实在我看来,完全没有这个必要。因为Load Generator已经支持UNIX了。从使用的角度说,Vuser Gnenerator没有必要做UNIX的版本,因为它还有Port Mapping的功能,这样在UNIX上的操作也照样录得下来。。
下面我们就单说LoadRunner的录制功能。
常规录制
首先,我们打开Vuser Generator,点击Start Record,出现如下界面:
在这个图中,首先的选择是:
这里用IE或者应用程序都可以,只要支持我们选择的HTTP协议就行。
Recording into action这里是默认的action,请你一定要注意的是init、action、end这三个都是action,并没有什么区别。控制init和end只执行一遍和action会重复执行多次的功能也不在它们自己身上,而是在run logic里。这一点我将在后面的文章中再细说。
点击Options之后,跳出界面如下:
在这个界面中,有很多可以调的内容。这里举几个重要的点。
首先是HTML-based script和URL-based script。
这个功能点之所以重要,是因为这两个选项录制出来的脚本有很大差别。
其实这一点和JMeter的Store 1st sampler for each group only是一样的含义。
如果选择了HTML-based script,就是一个页面一个请求了,而在回放和压力时,这个页面的所有资源都会请求。
如果选择了URL-based script,就是每个资源一个请求。这个选项有好处是,便于控制和查找问题。如果不想要某个资源,直接注释掉就好。
其次,我们需要注意关联功能。
你可以在这里事先设置好关联的规则,比如说这样的:
你就可以设置左边界为:JSESSIONID=,左边界为分号,然后在你录制的时候,如果规则匹配到就会自动创建关联。
点击OK之后就开始录制了。出现一个工具条,如下所示:
在这个功能条上具有的功能是:暂停、停止、新建Action,创建集合点、创建事务的起点和终端、加备注、加文检查点。
一般在业务流比较长的脚本中,
性能测试工程师都会通过新建Action把操作区分开,也会在录制过程中创建好必要的事务。
最后录制出的脚本如下:
注意哦,URL-based script的时候,有一个concurrent group,这个并发组是同时发出请求的。
在JMeter中有一个Parallel Downloads,你还记得吗?
这两者功能一样。
上面就是LR中常规的录制功能。录制前,看下readme,看LR支持什么浏览器。在版本12.6的readme中,已经声明支持Windows 10 + IE了。但是我们在使用的过程中还是遇到各种各样的问题,比如调不出浏览器、录不出脚本、卡死的问题。
还有,有些应用只支持Chrome,而有时,有些应用只能在某些特定的机器的执行,而那些机器又不能装Vuser Generator。
在这样的场景中,我们只能使用Port Mapping的功能。是的,在LoadRunner中,Port Mapping就是代理录制的方式。
Port Mapping
首先打开Vuser Generator,点击Start Record,配置成如下界面:
注意,这里一定要选择的是LoadRunner安装目录bin中的wplus_init_wsock.exe,从这个名字你也能知道它是基于Windows Socket的。
然后,点击Options - Port Mapping,如下所示:
点击New Entry。配置如下:
从上图中你可以看到,它的代理功能是很全面和强大的,不仅支持不同的Service ID,也支持SSL。
这时的访问逻辑是下面这样的:
一路OK,返回之后我们就可以开始录制了。会打开一个代理程序。截图如下:
这时候本地会开一个92的端口。
请注意,这时如果是远程访问,要注意不要让防火墙拦截了。
接着打开浏览器,输入地址http://10.211.55.3:92/,可以看到打开的是http://39.105.21.22:91/的界面。
同时,录制工具条中也显示出有事件产生。
当我们停止录制后,查看脚本如下:
看到没有,这里的访问IP在直接回放时是不对的。所以要将ip:port换成39.105.21.22:91才能回放。替换后如下:
这样就可以回放成功了。
如果回放不成功,我们就需要根据出错日志判断要做什么样的脚本增强。大部分的脚本都是需要做关联的,所以后面我们将讲一下关联的功能如何做,以及关联的原理。
Loadrunner的Port Mapping还可以支持FTP、SOCKET、POP等协议。这个功能点也不复杂,操作起来也简单,只要想明白访问链路就可以了。
LR的录制常用功能基本就这些了。
总结
这篇文章,应该是我写的所有的文章中,最最基础的一篇了,并且,从操作上,一步步地描述,也比较清晰。如果你有性能工具使用经验,肯定会觉得这篇过于简单。
可是为什么还要写呢?
因为在性能测试的过程中,有很多新手对录制的逻辑并不清楚。代理录制的这个动作他们也可以很快学会。但是很快就忘记了,我曾经给一些人手把手教过如何做代理录制。结果第二天就不记得了。其实并不是不记得动作,而是出了问题,脑子里没有判断问题的逻辑,所以根本无从下手排查。
另外,你需要注意的是,录制功能并不是性能测试工具必备的功能。对性能测试工具来说,关键功能是能实现模拟批量的真实请求逻辑。至于脚本是如何实现的,怎么做就是可以的。所以我们可以用其他的工具,比如说BadBoby、Fiddler甚至Wireshark抓到交互请求,再放到JMeter中实现脚本,也完全是可以的。
当然没有脚本就无从实现压力,所以脚本的实现是性能测试工程师必备的基础技术,理解原理也是必须的。
思考题
学完今天的文章后,你能用自己的话说一下代理录制的逻辑是什么吗?以及,当访问网页时,为什么第一个请求至关重要?
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流进步一下。
- zuozewei 👍(41) 💬(1)
第一个问题:代理录制的逻辑是什么吗? 你也许听过这样一句至理名言:“计算机科学领域里的任何问题,都可以通过引入一个中间层来解决”。TCP/IP 协议栈是这样,而代理也是这样。 所谓的代理(Proxy)是 HTTP 协议中请求方和应答方中间的一个环节。既可以转发客户端的请求,也可以转发服务器的应答。 代理常见种类:匿名代理、透明代理、正向代理、反向代理. 代理可以做的事:负载均衡、内容缓存、安全防护、数据处理。 此处简单理解 JMeter 录制脚本则通过代理是通过转发数据包并拦截上下行的数据解析生成脚本,但录制出来的脚本都是原始的 http 请求,并没有经过适当的封装,所以录制功能比较弱。 第二个问题:当访问网页时,为什么第一个请求至关重要? 实际上,对浏览器来说,他们做的事情,就是把一个 URL 变成一个屏幕上显示的网页。这个过程是这样的: 1.浏览器首先使用 HTTP 协议或者 HTTPS 协议,向服务端请求页面; 2.把请求回来的 HTML 代码经过解析,构建成 DOM 树; 3.计算 DOM 树上的 CSS 属性; 4.最后根据 CSS 属性对元素逐个进行渲染,得到内存中的位图; 5.一个可选的步骤是对位图进行合成,这会极大地增加后续绘制的速度; 6.合成之后,再绘制到界面上。 简单理解浏览器的工作原理就很容易回答这个问题了,第一次请求后需要构建 Dom 树(内存中的数据结构),而这棵 DOM 树其实就是前端程序的业务状态。
2019-12-31 - 月亮和六便士 👍(13) 💬(2)
上一篇与这一篇:姚明与郭敬明的差距
2019-12-30 - 王德发 👍(8) 💬(2)
录制APP请求:Script Recorder界面先设置https domain,输入localhost,然后将证书推送到手机,adb push ApacheJMeterTemporaryRootCA.crt /sdcard,再选择从设备安装证书,安装完成后,选择手动代理,输如jmeter所在机器的ip和代理服务端口,启动,操作APP就可录制了。
2020-01-09 - LensAclrtn 👍(6) 💬(1)
1. 代理录制的逻辑是什么? 不管是在本地代理还是远程代理, 都是通过代理的设置,在客户端和服务端之间插入一个中间件,中间件接手客户端的请求并转发到服务端. 说白了就是端口映射, 也就是老师文章里说的Port mapping 另外, 端口映射工作在传输层,重定向工作在应用层, 他们是两个东西 不知道我这么理解有没有问题? 2. 访问网页时,为什么第一个请求至关重要? 第一个请求如果都有问题,那后面就算有请求也没有再分析跟踪的必要来.
2019-12-30 - 牺牲 👍(5) 💬(1)
代理录制的逻辑,通俗讲客户端是用户,代理是服务员,服务端是后厨。请求是用户点菜对接服务员,服务员对接给后厨,也就是客户端的请求->代理->服务器;返回数据是后厨做好的菜品->服务员->用户。代理直接拿到请求内容,然后转发给服务端,服务端返回结果给代理,代理再转发给客户端。跟抓包工具的原理差不多。 第二个问题文章中写道:从 HTML 文件获取所有内含的资源和自动重定向将开启。也就是说,虽说只记录了一个 Sampler,但是资源也会下载,重定向也会开启。
2020-06-16 - 童话 👍(3) 💬(1)
在jmeter脚本录制之后会产生很多请求,在看某个业务响应时间不是非常直观,例如,打开首页—登陆—进入某个页面—输入信息—-提交,而只要看到提交响应的时间,但在查看聚合报告的响应会很多请求,对于是怎么处理的,是否能像loadrunner 只要看事物响应时间部分
2020-01-06 - helloworld 👍(2) 💬(3)
jmeter怎么去压测rpc协议呢? 比如说dubbo通信。 通过 Http -> dubbo client -> dubbo server ? 请问老师这有啥好办法吗?
2022-07-17 - yjluo 👍(2) 💬(1)
“设置左边界为:JSESSIONID=,左边界为冒号”loadrunner设置关联这里应该是写错了,右边界应该是分号
2021-01-11 - 有梦想的tester 👍(2) 💬(1)
我有一个jmeter脚本,登录...查询...购物...支付,我需要把他们都加到事务里去吗?网上的资料我没见有加事务的。
2020-03-21 - Geek_570c4c 👍(2) 💬(1)
代理是是中间件,转发客户端和服务器的交互协议包,生成脚本文件。 第一个请求最重要,第一个请求是创建dom树的,没有第一个请求,后面就没了。
2020-01-07 - buffalo 👍(2) 💬(1)
这一篇很实用,最近听高老师的段子有种追美剧的感觉😄 对locust很有兴趣,不知道后面是否会有涉及。个人感觉如果是python平台的话locust很容易使用,而且方便将性能测试用例自动调度执行插入CI环节做回归验证。使用起来与Jmeter有些不同,更方便对已有测试用例资产的重用
2019-12-31 - bolo 👍(1) 💬(1)
第一个问题: 代理录制的逻辑是什么? 代理的功能主要是用来做数据转发(请求内容及响应内容),代理是可以拿到所有的请求及结果的,所以可以将所有的请求及响应体内容保存下来用于后期的性能测试使用。 代理我们生活中用的比较多是访问国外的网站时候需要挂一个代理,通过代理我们可以访问Google,看YouTube。 第二个问题:看了留言才知道是DOM树。 其实工作中多数的性能测试工作 偏向纯接口的,主要还是通过手动填写的方式录入的.
2021-02-22 - 冬风向左吹 👍(1) 💬(1)
为啥我没有生成ca证书,生成了一个jks的证书,浏览器怎么导入呢? ProxyControl: HTTP(S) Test Script Recorder SSL Proxy will use keys that support embedded 3rd party resources in file /data/exec/apache-jmeter-5.3/bin/proxyserver.jks
2020-05-20 - 上不去的别上了 👍(1) 💬(1)
工具使用前了解其原理再上手就快多了
2020-03-22 - 小昭 👍(1) 💬(1)
思考题: 你能用自己的话说一下代理录制的逻辑是什么吗? 代理主要是做一个转发的工作。代理服务器/程序介于客户端和服务器之间,客户端发送的请求会被代理服务器/程序拦截,然后由代理服务器/程序转发到服务器上;服务器处理完这个请求后,返回的响应也被代理服务器/程序捕获,然后再转发给客户端。 当访问网页时,为什么第一个请求至关重要? 这个一开始没想到原因,看了评论才知道第一个请求是为了构建DOM树,用来存放后面的请求。 我用的是windows系统,导入证书那我直接通过浏览器导入,也可以实现。
2020-03-17