您的位置:首页 > 理论基础 > 计算机网络

ab源码分析 (2013-07-12 13:00:06) http://blog.sina.com.cn/s/blog_999d1f4c0101e18f.html

2015-09-07 20:45 561 查看


ab源码分析

(2013-07-12 13:00:06)


转载▼

标签:


linux编程


ab


工具


异步connect


epoll

分类: 工具
by nuyoag

ab(apache bench)是web服务器APACHE自带的压力测试工具。它通过模拟多个客户端同时对web服务器发起请求,对WEB服务器的并发性能进行测试。对于一般的服务器端程序,ab也提供了一种并发性测试的思路。本文将对ab的关键逻辑进行分析。ab的源码可以从http://code.google.com/p/apachebench-standalone/下载。

ab的使用说明如下:

Usage: ab [options] [http[s]://]hostname[:port]/path

Options are:

-n requests Number of requests to perform

-c concurrency Number of multiple requests to make

-t timelimit Seconds to max. wait for responses

-b windowsize Size of TCP send/receive buffer, in bytes

-p postfile File containing data to POST. Remember also to set -T

-u putfile File containing data to PUT. Remember also to set -T

-T content-type Content-type header for POSTing, eg.

'application/x-www-form-urlencoded'

Default is 'text/plain'

-v verbosity How much troubleshooting info to print

-w Print out results in HTML tables

-i Use HEAD instead of GET

-x attributes String to insert as table attributes

-y attributes String to insert as tr attributes

-z attributes String to insert as td or th attributes

-C attribute Add cookie, eg. 'Apache=1234. (repeatable)

-H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'

Inserted after all normal header lines. (repeatable)

-A attribute Add Basic WWW Authentication, the attributes

are a colon separated username and password.

-P attribute Add Basic Proxy Authentication, the attributes

are a colon separated username and password.

-X proxy:port Proxyserver and port number to use

-V Print version number and exit

-k Use HTTP KeepAlive feature

-d Do not show percentiles served table.

-S Do not show confidence estimators and warnings.

-g filename Output collected data to gnuplot format file.

-e filename Output CSV file with percentages served

-r Don't exit on socket receive errors.

-h Display usage information (this message)

-Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)

-f protocol Specify SSL/TLS protocol (SSL3, TLS1, or ALL)

其中,最常用的参数为-n和-c,这两个参数分别指定了向服务器发起的请求数量和并发程度。其它参数则主要针对HTTP请求和响应的格式以及ab的输出方式。

ab的实现依赖于APR(Apache Portable Runtime)库,该库对unix平台编程接口进行了统一的封装和扩展,但从名子可以很容易的看出它们之间的对应关系。本文不再赘述。ab在模拟并发访问时并没有使用多线程,而是使用了一种异步connect+epoll的方式来实现,下文主要对这一过程进行分析。

我们从ab的main方法看起,该方法主要对参数进行解析并设定了一些代表参数的全局变量,最后分别调用了以下方法:

copyright();

test();

apr_pool_destroy(cntxt);

即ab的主要逻辑包含在test方法中。test方法首先进行了一些全局的初始化工作。其中,最重要的一个数据结构是数组struct connection con[c],代表同时存在的c个客户端连接。struct connection的结构如下:

struct connection {

apr_pool_t *ctx;

apr_socket_t *aprsock;

apr_pollfd_t pollfd;

int state;

apr_size_t read;

apr_size_t bread;

apr_size_t rwrite, rwrote;

apr_size_t length;

char cbuff[CBUFFSIZE];

int cbx;

int keepalive;

int gotheader;

apr_time_t start,

connect,

endwrite,

beginread,

done;

int socknum;

int port;

#ifdef USE_SSL

SSL *ssl;

#endif

};

test方法首先调用start_connect开始c个初始的连接

for (i = 0; i < concurrency; i++) {

con[i].socknum = i;

start_connect(&con[i]);

}

start_connect首先创建一个socket端口并将其设置为非阻塞,这样调用connect时就会立即返回EINPROGRESS错误,但TCP三步握手仍在后台进行。通过这种方式,就可以同时发起多个连接,从而模拟多个客户端请求服务器的场景。start_connect的主要逻辑如下:

re = apr_connect(sock);
if(re == EINPROGRESS){
将sock加入到epoll的监控列表中,等待连接完成
}
else if(re == SUCCESS){
连接已完成,调用write_request发出请求,后文将介绍
}
else{
报错
}

返回test 方法,在创建完成初始的连接之后,test开始使用epoll来监听连接完成、有新的响应数据等事件并进行处理:

do{
do{
status = apr_pollset_poll(readbits, aprtimeout, &n, &pollresults);
}while (status == EINTR);

for(I = 0;I < n;++i){
……
rv = next_fd->rtnevents; //取epoll事件
if ((rv & APR_POLLIN) || (rv & APR_POLLPRI) || (rv & APR_POLLHUP))
read_connection(c); //读服务器端的响应数据
if ((rv & APR_POLLERR) || (rv & APR_POLLNVAL)) {
出错,此时调用start_connect重试连接
}
if(rv & ARP_POLLOUT){ //可写,如果连接完成则返回可写事件
if(处于CONNECTING状态){
rv = apr_socket_connect(c->aprsock, destsa); //此时再连接应直接返回
if (rv != APR_SUCCESS) {
重新调用start_connect开始连接
}
else{
//连接成功
调用write_request发送请求
}
}
}
}
}while(未完成)

上文中提到的write_request和read_connection分别为向服务器发出请求以及从服务器读取响应数据的方法。其中write_request方法会将预先创建好的http请求的内容一次性发送出去;而read_connection则尝试读取、解析服务器端响应并在读取到EOF后调用close_connection方法关闭当前连接。

最后, close_connection方法除了关闭socket端口、记录结果外,如果请求数未达到要求时还会复用要关闭的struct connection,重新调用start_connect发起连接请求,从而推进测试任务。

在一般的操作系统中,单个进程能够新建的线程数量是有限的。通过使用异步connect的方式代替多线程,ab可以提高客户端能够达到的并发程度,从而提高测试能力。虽然ab本身是针对http服务器的测试工具,但这种设计可以被用来对任何服务器端程序进行并发性测试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: