您的位置:首页 > 运维架构 > Apache

Apache Benchmark修改,支持发送不同数据包

2015-06-13 14:20 621 查看
起因是,工作中一些接口需要性能测试,首先考录本地代码的测试工具,因为测试工具本身的性能开销很小,更加合适,然后AB(Apache Benchmark)简单便捷,但是,AB的-p参数只支持读取一个post数据文件,然后重复发送一样的内容,在我的接口处理同样数据时,只有第一次是真正的新增,而后只是快速返回之前的数据,所以这并不能体现新增接口的性能。

为了寻求使用AB实现每次发送不同的POST数据,翻了下源代码。

AB的实现很简单,根据不同参数拿到不同的值,直接存到一堆全局变量里面。test函数负责读取一些全局变量,创建socket连接,使用非阻塞的socket,同时创建C个连接,通过-c参数指定的并发数就是这里的连接数,这里并不是多线程去请求,因为是非阻塞,所以直接循环connect即可实现并发。然后用异步的epoll方式取处理封装好的Http请求header及body。发送的次数N由参数-n指定。请求完成之后output_html_results函数或output_results函数计算请求时间之类的结果并输出。

下面来分析下-p参数,-p指定一个文件,这个文件存有Http请求的body。open_postfile函数读取文件内容。apr_file_open,apr_file_info_get,apr_file_read_full是APR库里面封装的文件操作系列函数。AB中用apr_file_read_full读取整个文件内容并存储在全局变量postdata(buffer containing data from postfile)中,然后发送的时候将其拼装到Http的Body通过Socket发送给url。

根据以上-p的原理,只要自己来指定一种格式,读取包含多个Http请求Body的文件后,解析出多个Body,组成多个Http包,然后每次发送不同的Http包即可。所以改动点主要有3个:

1. 添加一套全局变量,其中request_multi表式一个二位数组,包含不同的Http包,制定-m参数表式发送多重post请求

2. 添加读取并解析特定格式buffer的状态机

3. 发送不同的buffer与。

在原始代码中,write_request函数中:

e = apr_socket_send(c->aprsock, request + c->rwrote, &l);


这个函数是APR封装的send函数,request是在test函数中预先根据postdata拼装好的Http包buffer,c->rwrote是发送完成偏移量。问题在于,多个不同的buffer需要使用二维数组来存储,然后为了发不同的内容需要每次指定一个数组下标取不同的buffer。上述的write_request,每次调用发送的都是同样的内容。重写另一个wirte_request成本稍微比较大,而且大部分代码会是一模一样的,好在发现了另一个全局变量:started(number of requests started, so no excess),每个buffer发送成功后,这个变量会自增,刚好可以用来当作二维数组下标来用,只要用另一个变量区分以下当前是发送多重Post从而发送request_multi即可。

现在规定的文件格式如下:

count\n
post1\n
===>
post2\n
===>
postn\n
...


其中,count指定当前文件的请求数,实际上-n参数指定的值会被count覆盖。

内存使用的一点分析:

AB本身每个Http包的长度最大2048字节,每次最大请求数50000,按此最大值来算一次读取的文件最大需要内存 2048 * 50000 * 3 == 300M,乘以3因为第一次读取文件存入buffer,第二次解析存入post buffer,第三次post buffer拼装成request buffer。第一次第二次的相当于两次的复制过程,复制完成之后可以直接free掉。不过AB本身的使用场景决定,全部请求发送完成之后进程直接退出,保证其所有内存全部被系统回收。

AB源码是在Apache Httpd的support下的,我用的是Httpd2.4,比2.2的代码整齐一些。

代码(依赖APR):https://github.com/fankux/ApacheBenchmarkMulti

另外,水平有限,欢迎随时拍砖!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息