Vugen 的 Proxy 方式需要解决的一个问题是二次捕获数据包的问题。
早期的网络服务器程序对外提供一个固定端口,客户端仅仅和这个端口通讯就可以了。这对于 proxy 录制非常容易。但是现在很多服务器程序为了提高对客户端并发量的支持,采用两个端口通讯的方式。如下图所示:
整个通讯的过程如下:
· 第一步:客户端将请求发往 Proxy 录制器。
· 第二步: Proxy 录制器将请求发往真正的服务器的指定端口,即图中的 3200 端口。
· 第三步:服务器机器的 3200 端口返回数据包给 Proxy 录制器。该数据包中包含了下一次通讯的目的地址,形式为 IP:Port 。很显然,这里的 IP 数据为真正服务器的 IP 地址。
· 第四步, Proxy 录制器把请求返回给客户端。
· 第五步,客户端根据提供的 IP:Port 信息直接把请求发往真正的服务器,不再经过 Proxy 录制器。
· 第六步:以后的通讯只是客户端和服务器之间的通讯了, Proxy 录制器是无法捕获这些通讯包了。
因此一般的 Proxy 录制器只能捕获头两个收发的数据包。 这个问题更一般的情形的例子是 HTTP 的 redirection 功能。第二次通讯可能发往另外一台机器了。 Proxy 录制器必需解决这个问题。
· 关联的问题
客户端和服务器之间的通讯,有一部分是数据是动态的,每次通讯都不一样。 Proxy 录制器在录制的时候是无法区分哪些是静态的信息,哪些是动态的信息,所有的信息都以 hard-coded 的方式记录下来。但是在回放的时候,如果有些信息不改变,那么脚本是不能执行成功的。考虑如下情形:
如上图所示,用户 jojo 以 jojo/bean 的账号 / 口令登录某一 web 服务器,查询某产品的信息,由 Vugen 录制交易的全部通讯包。 web 服务器返回给 jojo 一个动态的会话 ID: SessionID@12345 ,作为这次登录的会话标识。由于 Vugen 无法知道哪些信息是动态的,它会照单全收的方式,把所有的数据就记录下来。接着 jojo 根据 Web 服务器告诉他的 SessionID 去查询产品列表,交易可以正常执行下去。
我们会观察到,当 Vugen 根据捕获的通讯包生成 http 脚本的时候, SessionID 是 Hard-coded 的,即 “ 写死 ” 在程序里面的。当我们不加修改的回放该脚本的时候,会出现什么问题呢?如下图所示:
按照录制时候的脚本, jojo 以 jojo/bean 登录后, Web 服务器返回给 jojo 一个动态会话 ID: SessionID@23456 ,这个值已经不是录制时候产生的 SessionID@12345 了,而是新的值: SessionID@23456 。那么脚本根据记录的 SessionID 的值,仍然会使用 SessionID@12345 去执行下面的查询交易。由于会话 ID 是有时效性的,用户退出系统后,其 SessionID 会失效,那么,服务器会给出一个 “SessionID 失效 ” 的错误,从而导致脚本无法正常执行下去。
对于上面的问题的通用解决方法如下图所示:
在第一次从服务器得到 SessionID 的时候把其放在一个变量 <session_id> 里面,在后面脚本访问服务器的语句里面,把所有的 ”SessionID@12345” 替换为变量 <session_id> 就可以圆满解决这个问题。
这种问题在任何系统都是非常常见对外问题。其通用的模式是: “服务器返回给客户端一些动态变化的值,客户端使用这些值去访问服务器的时候,不能把这些值写死在脚本里面,而应该存放在一个变量里面。” 这就是关联的概念。
关联的工作往往占据开发脚本的大部分时间,因为我们必需针对每一个具体的系统进行细致的分析,确定其需要关联的动态信息。为了快速开发脚本, Vugen 必需提供帮助我们关联的手段,最好做到自动关联。自动关联的方法有三种:
· 在录制之前设定辨别规则,录制完毕,产生脚本的时候根据规则识别出需要关联的动态内容,从而产生正确的脚本。
· 录制完毕回放一遍,把回放结果与录制结果进行自动对比,确定动态信息,进行自动关联。
· 录制两个一模一样的脚本,对比其中的差异来确定需要关联的动态信息,然后进行关联。
自动关联的功能是否完整可靠,关系到我们能否借助 Vugen 快速开发出符合要求的脚本,因此关联也是 Vugen 中非常重要的功能。
· 脚本的问题
Vugen 产生的最终结果是以源程序方式存在的脚本。为了编译该脚本,用户可以选用对应的编译器,这不是 Vugen 的功能。建议 Vugen 产生脚本的时候应该生成对应的 Makefile 和 build.xml ,允许用户以流行的 make 和 ant 命令来编译 C 和 Java 的脚本。关于 make 和 ant ,读者可以在互联网上查询相应的内容。
Vugen 自动产生的脚本应该支持两种语言, C / Java 。很显然, Vugen 不可能产生一个脚本运行的全部的代码,它需要额外的函数库的支持。譬如,通过录制 Tuxedo 协议产生的脚本应该是以 Tuxedo-API 的形式出现的。为了能够编译运行脚本,必需把 Tuxedo 的函数库连接到脚本里面。目前动态库的技术应用非常广泛,因此为了运行 Tuxedo 脚本,必需在 Vugen 和 Player 机器上安装相应的 Tuxedo 客户端软件,因为它包含相应操作。其它网络协议也存在这个问题。对于 http 协议,已经有很多函数库。 Vugen 产生的 http 脚本应该支持主流的函数库。这样带来的好处是我们不需要自己开发 http 函数库,可以直接引用已经经过实践证明了的质量可靠的函数库。选择支持何种函数库,需要慎重选择,我们应该选择应用最广泛的函数库。例如:关于 http 函数库,可以采用 www.w3c.org 提供的 libwww ,该函数库是开源的,质量可靠,远胜于我们自己开发。
· Conductor 和 Player 部分
Conductor ,我们称为 “ 指挥家 ” ,它是整个压力测试的核心。 Player 是产生压力的负载产生器,它们以进程或者线程的方式运行由 Vugen 生成脚本。 Player 如何运行脚本,由 Conductor 来决定。这好比一个交响乐队在演奏。 Player 就是各种管弦乐演奏者, Conductor 是指挥者。
Conductor 和 Player 实际上是一套框架程序。具体执行什么功能,是由脚本来完成的。 Conductor 和 Player 的体系结构如下图所示:
如上图所示, Conductor 上面有若干进程 / 线程。每种进程的作用如下:
· Center 进程是整个调度的核心进程,它负责联系和用户界面打交道的工作。
· Agent 进程负责和远端的 Player 机器中对应的 Agent 进程通讯。负责把编译好的脚本传送到 Player 机器上。在脚本运行的时候,定期从 Player 机器上获取 Player 的运行状态,每个虚拟用户运行的日志。
· Monitor 进程负责对被测试系统的各个环节进行监控,并把监控的内容一方面写入 Conductor 机器的本地磁盘,另外一方面把监控的内容传送给 Center 进程,实时地显示在用户界面上。
Player 的进程有两种,一个是 Agent 进程,一个是 Player 进程。 Agent 负责和 Conductor 机器通讯,它根据 Conductor 的指示,在本机器上派生出指定数目的 Player 进程,这些 Player 进程负责具体执行相应的脚本。 Player 进程个数就是虚拟用户的个数。
Player 需要解决的一个问题是 IP 问题。为了防止黑客的攻击,某些后台的负载均衡设备一旦发现来自某一个 IP 的请求特别频繁时,就会拒绝为该 IP 提供服务。这样的功能造成的结果是 Player 无法把真正的压力加到后台系统中。解决方法就是在 Player 机器上伪装多个 IP 地址发送请求。这项技术称为 IP 欺骗 (IP Spoofling) 。 Conductor 和 Player 必需实现该项功能。
· Conductor 和 Player 的技术要点
关于 Conductor 和 Player 的技术要点有哪些,目前我还没有做深入的研究工作,但是我认为其技术要点主要涉及多进程 / 线程的编程,网络编程技术。可能这里面最大的难点是监控问题。当把被测系统的各个环节都监控起来,需要监控的参数会有成百上千个。如果采用集中式监控的方式,采集数据本身就对系统造成很大的影响,所以必需支持分布式监控方式。由于采集的数据是来自不同机器上的,由于各种的延迟,数据之间的时间同步将是一个重大的问题。
关于监控,还需要进一步的研究。
由于 Player 是没有界面的,是后台运行的程序,为了保持其可移植性,建议采用 Java 语言开发。
Player 和 Conductor 之间的网络协议不一定重新开发,可以使用成熟的 Http 1.1 ,方便在性能测试时调试 Player 和 Conductor 之间可能出现的通讯问题。
· 数据分析工具 Analysis
该工具是一个纯数学工具软件,目前市场上已经存在了大量负责数据处理的软件,如 Matlab 等。可以将压力产生的数据直接导入其中进行处理。所以只要提供开放的数据接口就可以了,无需自己开发独立的性能数据分析软件。
即使 Analysis 需要开发,应该开发一些知识分析的功能。譬如,我们搜集了很多 Oracle 的数据信息,这些数据之间往往有固定的联系。如果将这些联系的知识融入到 Analysis 当中,将会更好。但是这有点类似人工智能的意味,比较难。
· 结束语
本文是对性能测试工具的一般性论述,讨论了性能测试工具的基本功能和可能出现的技术要点。由于性能测试工具涉及的内容太多,作者只是大致论述。其中涉及细节当中仍然会有很多技术要点没有论述。只是希望本文对希望了解性能测试工具的读者有一个入门的帮助。
一套功能全面的性能测试工具就象水管工经常携带的工具箱,里面充满各种工具,这些工具经过组合可以完成任何复杂的机械工作。完全从头开发这套工具箱,工程浩大,靠业余的编程爱好者是很难完成的。但是我们应该吸取 Unix“ 小而灵活 ” 的哲学思想,在一个大的框架下面开发或者利用已经存在的开源工具软件制造出一个个灵活的部件。当把这些部件组合起来以后,就是一个功能完整、质量可靠的性能测试工具箱。


最新评论
查看全部评论
评论总数 1 条