gitbook/性能测试实战30讲/docs/183349.md
2022-09-03 22:05:03 +08:00

353 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 07丨性能测试工具如何录制脚本
对于一个性能测试工具来说,如果能实现以下几大功能,那么就基本上就满足了性能测试工具的功能。
1. 录制或编写脚本功能
2. 参数化功能
3. 关联功能
4. 场景功能
5. 报告生成功能
但是除此以外,在工作的细节上还有更多要求,就要看工具的实施能力了。
有很多性能测试工程师希望工具能做得非常全面,又人性化,而纵观当前的性能工具,真正能够做到傻瓜式录制完脚本,自动设置好参数化、关联、场景,直接产出结果的工具是没有的。不管是云性能测试平台,还是分布式性能测试工具(当然性能测试工具几乎全部具有分布式能力),都需要性能测试人员来定义参数化数据、设置关联、配置场景。
因此,在性能测试的过程中,对工具的配置就成为了性能测试工程师的基本能力。
今天,我们就来看下在性能测试工具中,如何录制脚本。今天的文章有些特殊,可能是专栏中少有的,有详细操作的文章。
## 性能工具的脚本能力
性能测试工具的脚本编写能力分为两类,一个是录制,另一个是手工编写。
现在市场上的性能测试工具虽然支持录制功能但大部分也只是支持HTTP协议。在我们熟知的工具中也只有LoadRunner支持更多协议的录制能力。不过幸好现在我们所面对的应用大部分是HTTP协议的应用。
对手工编写脚本的部分,因为大部分都取决于业务场景,所以很难提出共性。如果有人提出针对性的场景,我们再做相应的示例就行。
因此今天的文章将着重讲一下测试工具的录制功能。很多人以为性能工具录制功能非常简单,点几下就能生成一个脚本,但是录制完之后,针对脚本的增强完善就做得非常少了。事实上,针对脚本,我们不仅要录制下来,还要了解录制的原理和录制完之后的脚本增强。不然,在场景中还是会遇到各种各样的问题。
## 性能工具中的录制功能
录制功能从原理上来说,分成两种:
1. 本地录制通过截取并解析与服务器的交互协议包生成脚本文件。比如说LoadRunner调起IE的时候不用修改IE的代理设置就可以直接抓取HTTP包并通过自己的解析器解析成脚本。
2. 代理录制通过代理服务器设置转发客户端和服务器的交互协议包生成脚本文件。JMeter中的脚本录制功能就是这样做的。
这两者的不同点主要在于操作上。本地录制相对简单,但有些场景受限,比如说操作只能在某台服务器上,但是这台服务器又不允许安装工具;代理录制操作复杂一些,但可以满足更多的场景。
通过这张图,我们可以简单看到代理录制的逻辑:
![](https://static001.geekbang.org/resource/image/2c/49/2c444b52c9b614bd7779394e6ed18849.jpg)
1. 我们在IP为2.2.2.2上的主机上打开一个代理程序开81端口所有到81端口的都转发到1.1.1.1的80端口。
2. 当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。界面如下
![](https://static001.geekbang.org/resource/image/df/f8/df8730ffbbfb0e68879a88e8699035f8.png)
这里有几个关键点说明一下:
* Target Controller这里指定录制出的脚本要放到哪里去。如果你想把不同的脚本放到不同的线程组中去在录制的时候就可以拆分开。
* Grouping分组这个分组功能很实用。但是如何分组就和具体的目标相关了这一点下面我们再细说。
点击start按钮时会提示创建一个根CA证书。这个证书生成在bin目录中文件名是ApacheJMeterTemporaryRootCA.crt七天有效期。这个证书将被用来客户端转发HTTPS的请求。与此同时还有另一个证书在同目录中生成名字是proxyserver.jks这是JMeter自己生成的根证书。
![](https://static001.geekbang.org/resource/image/be/19/be8ef3815ed27b60f11aae9679457219.png)
前面我们说到了JMeter是用代理的方式来录制的。如果服务端用了SSL证书在代理时也要加SSL证书那么代理录制的结构就会变成这样。
![](https://static001.geekbang.org/resource/image/8f/c9/8f51e323947ca6b8109241f1c71e0ec9.jpg)
上面的SSL证书就是用来处理上图中蓝色的这一部分。
我们点击ok之后就会出现这个界面。在这个界面中只有两个配置项。
* Prefix请求名的前缀。
* Create new transaction after request(ms):一个请求完成之后,如果下一个请求超出了这里设置的时间间隔,就创建一个新的事务。
![](https://static001.geekbang.org/resource/image/bf/ff/bff35c026d490ec75425a0d6e41a36ff.png)
然后到主机上设置代理。
注意这里我要敲黑板了呀这里的代理设置是在需要访问的客户机上。这个客户机不一定是压力机所在的机器。这里的localhost也应该设置的是代理服务所在的主机IP。
![](https://static001.geekbang.org/resource/image/74/49/74e3652701b526509b410790f0fa2549.png)
请注意如果你要设置为录制HTTPS还需要做如下两步。
第一步是浏览器代理要把Secure Web Proxy(HTTPS)选择上同时填上相应的代理IP和端口下图是macOS上的图示。
![](https://static001.geekbang.org/resource/image/b3/46/b3ef5c0c4ce44566ee31157c17cd1846.png)
但你会发现这时仍然录制不了HTTPS应用访问时会出现如下提示
![](https://static001.geekbang.org/resource/image/35/4f/3530bde553697ac448eac94e26ee524f.png)
这时就要在客户端机器上导入上面提到的ApacheJMeterTemporaryRootCA.crt。我们打开证书管理软件在macOS上是Keychain AccessWindows上是certmgr.msc。
这里以macOS为例。
首先打开Keychain Access。
![](https://static001.geekbang.org/resource/image/68/2e/6861248706928c135e68bed9ee28232e.png)
点击上图中的Import Items。选择ApacheJMeterTemporaryRootCA.crt导入之后选择证书。会看到如下提示
![](https://static001.geekbang.org/resource/image/dd/92/ddfdc4ef2050f922c9ea1b7ed3977d92.png)
因为这个证书不在系统信任的默认列表里,所以会提示证书不可信。
另外这里我可以再多说一句你注意的是全球的可信任的根证书都是默认添加到系统中的如果你在访问网站时提示你要安装什么证书一定要明确知道证书是从哪来的不要随意安装未知来源的证书。目前国内的HTTPS覆盖度不高仍然有大量的HTTP网页这是需要推进的网络安全之一。
然后我们双击此证书。
![](https://static001.geekbang.org/resource/image/f7/16/f779bc63cd421ba92b1de098899b5616.png)
改为Always Trust即可。提示如下
![](https://static001.geekbang.org/resource/image/41/8c/417c1e58d3081ca6515ec8977532b78c.png)
这时HTTP和HTTPS都会被录制下来。然后在客户机上打开浏览器访问你的页面这样就录制到脚本了。
下面我们再来说下Grouping这个功能。
Grouping的设置有如下几种如果需要将脚本分开先确定需要如何拆分。示例如下
![](https://static001.geekbang.org/resource/image/22/8b/2214f144340139acd8c84a15c86c938b.png)
第一个选项是Do not group samples也就是不分组。
这是很多人使用的默认选项这就相当于没有事务的概念了每个请求都会单独统计TPS和响应时间信息。
![](https://static001.geekbang.org/resource/image/41/83/41bb7af036a9910db9d8fd4bb6cf4083.png)
第二个选项是Add separators between groups在组间添加分隔就为了好看
![](https://static001.geekbang.org/resource/image/25/35/251bcebb7e4451c881ba718ca21d6535.png)
第三个选项是Put each group in a new controller每个组放一个新的控制器。这是一个Simple Controller它的作用也是只有一个就为了好看
因为脚本太长了看起来不方便所以分个组看着清晰一些。话说回来你们见过在JMeter中有很长脚本的吗是不是很多人都没有见过
![](https://static001.geekbang.org/resource/image/74/0a/7451c99638e005cfe98d80ed0def060a.png)
第四个选项是Put each group in a new transaction controller将每个组放入一个新的事务控制器中。
![](https://static001.geekbang.org/resource/image/9b/34/9b5766b5a61fe76ed82a33f671ae9c34.png)
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。抓出如下结果。
![](https://static001.geekbang.org/resource/image/5a/a4/5a24f2adae925faac98b057a507525a4.png)
在上面的图中你可以看到www.jd.com第一个就是307 Internal Redirect。接着请求Document然后下面是静态资源。在录制时选择Store 1st sampler for each group only之后只会录制到第一个请求而后面这些在回放脚本时也都会访问。
在JMeter的代理录制中还有一个界面如下
![](https://static001.geekbang.org/resource/image/96/0d/968fe93634c0f18c806fa922f300d50d.png)
中文界面中通常将之翻译为包含模式、排除模式。“模式”一词一加就显得格外高大上了。
通常这里都会写上正则表达式,比如说常用的一些:
```
.*
.*.png
.*.gif
.*.jpg
.*.php
.*.jsp
.*.html
.*.htm
.*.js
..(js|css|PNG|jpg|ico|png|gif).
```
由于正则是一个很大的话题,这里我们就不展开了,只要你懂正则,在这里就可以适用。
通过上面的内容我们已经把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出现如下界面
![](https://static001.geekbang.org/resource/image/c7/67/c79f3d7d072478b223d557987951c767.png)
在这个图中,首先的选择是:
![](https://static001.geekbang.org/resource/image/0c/b7/0c0600701f1c6b71c8389eb243ab8bb7.png)
这里用IE或者应用程序都可以只要支持我们选择的HTTP协议就行。
Recording into action这里是默认的action请你一定要注意的是init、action、end这三个都是action并没有什么区别。控制init和end只执行一遍和action会重复执行多次的功能也不在它们自己身上而是在run logic里。这一点我将在后面的文章中再细说。
点击Options之后跳出界面如下
![](https://static001.geekbang.org/resource/image/21/c9/21e1969112927b0e16adc2e013241cc9.png)
在这个界面中,有很多可以调的内容。这里举几个重要的点。
首先是HTML-based script和URL-based script。
![](https://static001.geekbang.org/resource/image/d5/16/d57f3c15ea014cf1502e136a590b4e16.png)
这个功能点之所以重要,是因为这两个选项录制出来的脚本有很大差别。
其实这一点和JMeter的Store 1st sampler for each group only是一样的含义。
如果选择了HTML-based script就是一个页面一个请求了而在回放和压力时这个页面的所有资源都会请求。
如果选择了URL-based script就是每个资源一个请求。这个选项有好处是便于控制和查找问题。如果不想要某个资源直接注释掉就好。
其次,我们需要注意关联功能。
![](https://static001.geekbang.org/resource/image/52/43/52e00fd4eb4e6dab16f0acee5031d843.png)
你可以在这里事先设置好关联的规则,比如说这样的:
```
JSESSIONID=5687300192384o4^&&^&890523#123456;
```
你就可以设置左边界为JSESSIONID=,左边界为分号,然后在你录制的时候,如果规则匹配到就会自动创建关联。
点击OK之后就开始录制了。出现一个工具条如下所示
![](https://static001.geekbang.org/resource/image/2d/93/2dac210c135e85e99d8e0405d72a3093.png)
在这个功能条上具有的功能是暂停、停止、新建Action创建集合点、创建事务的起点和终端、加备注、加文检查点。
一般在业务流比较长的脚本中,
性能测试工程师都会通过新建Action把操作区分开也会在录制过程中创建好必要的事务。
最后录制出的脚本如下:
![](https://static001.geekbang.org/resource/image/9f/3c/9fe88180c56b27edd542db9ff715d73c.png)
注意哦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配置成如下界面
![](https://static001.geekbang.org/resource/image/55/37/554a3e2ef78259e73ecc4616bc176c37.png)
注意这里一定要选择的是LoadRunner安装目录bin中的wplus\_init\_wsock.exe从这个名字你也能知道它是基于Windows Socket的。
然后点击Options - Port Mapping如下所示
![](https://static001.geekbang.org/resource/image/84/29/847bf5c6d80b59f3772cb07d12c95929.png)
点击New Entry。配置如下
![](https://static001.geekbang.org/resource/image/b3/49/b39d5e0317acd982a42f97f5689a0d49.png)
从上图中你可以看到它的代理功能是很全面和强大的不仅支持不同的Service ID也支持SSL。
这时的访问逻辑是下面这样的:
![](https://static001.geekbang.org/resource/image/0a/8e/0ab937e601a8f2029527be1ccb0de08e.jpg)
一路OK返回之后我们就可以开始录制了。会打开一个代理程序。截图如下
![](https://static001.geekbang.org/resource/image/b8/36/b8cc2119b6eeb7164bbb47987d88ed36.png)
这时候本地会开一个92的端口。
![](https://static001.geekbang.org/resource/image/59/74/591d5598781d5a107b2d56f93a2e6f74.png)
请注意,这时如果是远程访问,要注意不要让防火墙拦截了。
接着打开浏览器输入地址http://10.211.55.3:92/可以看到打开的是http://39.105.21.22:91/的界面。
![](https://static001.geekbang.org/resource/image/dc/ca/dc5d435bca5f519905a7e49db49e72ca.png)
同时,录制工具条中也显示出有事件产生。
![](https://static001.geekbang.org/resource/image/5d/84/5d4e718b7cfd98398b4dc915180b5784.png)
当我们停止录制后,查看脚本如下:
![](https://static001.geekbang.org/resource/image/3a/98/3acc0dac595c23bedc5229f966d15398.png)
看到没有这里的访问IP在直接回放时是不对的。所以要将ip:port换成39.105.21.22:91才能回放。替换后如下
![](https://static001.geekbang.org/resource/image/7d/eb/7d699171119d5aab83af784220e421eb.png)
这样就可以回放成功了。
![](https://static001.geekbang.org/resource/image/61/d8/613e6d89e4480263bbce1c2aa08f0dd8.png)
如果回放不成功,我们就需要根据出错日志判断要做什么样的脚本增强。大部分的脚本都是需要做关联的,所以后面我们将讲一下关联的功能如何做,以及关联的原理。
Loadrunner的Port Mapping还可以支持FTP、SOCKET、POP等协议。这个功能点也不复杂操作起来也简单只要想明白访问链路就可以了。
LR的录制常用功能基本就这些了。
## 总结
这篇文章,应该是我写的所有的文章中,最最基础的一篇了,并且,从操作上,一步步地描述,也比较清晰。如果你有性能工具使用经验,肯定会觉得这篇过于简单。
可是为什么还要写呢?
因为在性能测试的过程中,有很多新手对录制的逻辑并不清楚。代理录制的这个动作他们也可以很快学会。但是很快就忘记了,我曾经给一些人手把手教过如何做代理录制。结果第二天就不记得了。其实并不是不记得动作,而是出了问题,脑子里没有判断问题的逻辑,所以根本无从下手排查。
另外你需要注意的是录制功能并不是性能测试工具必备的功能。对性能测试工具来说关键功能是能实现模拟批量的真实请求逻辑。至于脚本是如何实现的怎么做就是可以的。所以我们可以用其他的工具比如说BadBoby、Fiddler甚至Wireshark抓到交互请求再放到JMeter中实现脚本也完全是可以的。
当然没有脚本就无从实现压力,所以脚本的实现是性能测试工程师必备的基础技术,理解原理也是必须的。
## 思考题
学完今天的文章后,你能用自己的话说一下代理录制的逻辑是什么吗?以及,当访问网页时,为什么第一个请求至关重要?
欢迎你在评论区写下你的思考,也欢迎把这篇文章分享给你的朋友或者同事,一起交流进步一下。