接下来笔者以自己参与开发的一个大型电信项目为依托,结合自己设计和实现的TUXEDO服务器压力测试工具来分析一下压力测试中的一些方法和过程,以及要注意的问题。
压力测试必须有一定数量的并发客户端。为了测试,准备大量的PC,并在每一个上装一个client程序是不现实的,而且难以做到真正的并发,也不利于客户端数目不断变动的大量的测试,因此我们采用了软件模拟客户端的方法。对TUXEDO服务器而言,每一个客户端就是一个和它通信的进程,所以需要多少客户端简单的说就是开多少调用服务的进程,这个在OS的支持下是很容易实现的。这里有一个问题需要讨论,一般会想到用一个现成的压力测试软件来做。实际中发现,这种方式是有问题的。一般压力测试工具的方法是截获一个client到server的调用数据包,分析其中的数据,然后将一些数据进行参数化,例如一些ID等,然后生成一个可以产生大量并发的同类数据包的脚本,运行该脚本就可以进行压力测试,当然其中包括了很多度量。对于某些应用,例如新开户等,这种方法可以工作得很好,但是对于那些对数据真实性要求很高的服务,这种方法就难以实现。例如笔者做的压力测试中涉及的主要TUXEDO服务——用户帐单的查询和销帐处理。由于用户的电话号码或者帐号等通常是不连续的,中间有很多的空洞,而且销帐的服务是依赖于查询的返回结果的,如果不是数据库中一条真实的可以做销帐处理的帐单是不能成功的完成销帐流程的。这对构造数据带来很大的难度,而且那种构造出来的数据和实际的情况会有很大的差距,因为那可能被数据库的缓冲等进行优化,不能反映真实的性能,而最好的办法当然是用实际数据库中的真实数据。当然,这种真实也可以有一定的扩充,下面会涉及到关于压力测试数据的准备问题。通过上面的讨论,我们知道在一些实际的系统中,让了解系统应用的人自己动手来做压力测试很多时候是一个更好的选择。不必担心这个工作的复杂性,下面我们就相关的问题开始详细的分析。
1.模拟出指定数目的客户端。
开多进程需要OS的支持,下面以UNIX为例给出了一个实现的代码。需要特别注意的是后面注释有*的那一行代码,该行的意义是在子进程(pid=0,fork对父进程和子进程有不同返回,参考[1])中不再执行该循环。在UNIX中,子进程从fork()的下一句开始执行。如果没有上面那一句,新开出的子进程发现满足for循环的条件将继续执行循环,开出新的它自己的子进程,这样会产生复杂的进程树,可以计算那样得出的子进程的数目为。为更好的控制客户端的数量和保持进程相互关系的简明,我们通过上面那一句使得进程的关系只有两层,而且进程数目就等于P_NUM。
for ( i = 0; i < P_NUM; i++ ) //P_NUM为要开的进程数,也就是模拟客户端的数目
{
if ( (pid = fork()) == 0 ) break; //*
if ( pid < 0 ) exit(0);
}
if ( pid == 0 ) //子进程代码
{