压力测试工具Webbench源码分析
原理
webbench首先fork出多个子进程,每个子进程都循环做web访问测试。子进程把访问的结果通过pipe告诉父进程,父进程做最终的统计结果。
项目地址:
http://home.tiscali.cz/~cz210552/webbench.html
程序结构
主函数:
main函数解析参数,调用bench();
bench():
检查目标服务器是否可用:
i = Socket(proxyhost==NULL?host:proxyhost,proxyport);
创建pipe;(pipe声明:mypipe[2];)若成功返回0,否则返回-1。其中pipe[0]是读管道,pipe[1]是写管道。参考网址。
开辟子进程。
for(i=0;i<clients;i++)
{
pid=fork();
//…
}
关于fork()函数参考这里,子进程返回0,父进程返回子进程标记,否则返回0.如果是子进程,调用
benchcore(host/proxyhost,proxyport,request)
。将数据speed,failed,bytes的结果写入pipe。f=fdopen(mypipe[1],"w");
fdopen取一个现存的文件描述符,并使一个标准的I / O流与该描述符相结合,转换成功时返回指向该流的文件指针。失败则返回NULL,并把错误代码存在errno中.
fdopen参考这里如果是父进程,循环从文件中读取数据,直到只剩一个进程为止。统计并输出最终结果。这里用到一个函数
setvbuf
,这个函数是设置缓冲区的,这里用_INOBF
是无缓冲区,直接从流数据中读取。参考
benchcore():
- 设置计时器时间为benchtime,利用sigaction.
- 连接s=soket(host,port);
- write(s,req,rlen)写入请求。
- shutdown(s,1)关闭写请求。
- 如果force==0即不用等待服务器返回,读取socket中所有的数据i=read(s,buf,1500)。
- close(s)
alarm_handler():
计时器超时函数,设置timerexpired=1;
socket函数源码
int Socket(const char *host, int clientPort)
{
int sock;
unsigned long inaddr;
struct sockaddr_in ad;
struct hostent *hp;
memset(&ad, 0, sizeof(ad));
ad.sin_family = AF_INET;
inaddr = inet_addr(host);
if (inaddr != INADDR_NONE)
memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
else
{
hp = gethostbyname(host);
if (hp == NULL)
return -1;
memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
}
ad.sin_port = htons(clientPort);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
return sock;
if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)
return -1;
return sock;
}
Webbench的安装和使用
[root@node1 ~]# yum install -y gcc ctags
[root@node1 ~]# wget http://www.ha97.com/code/webbench-1.5.tar.gz
[root@node1 ~]# tar -xvf webbench-1.5.tar.gz
[root@node1 data]# cd webbench-1.5
[root@node1 webbench-1.5]# make && make install ##这一步可能遇到如下错误,手动创建目录即可
cc -Wall -ggdb -W -O -c -o webbench.o webbench.c
webbench.c: In function 鈥榓larm_handler鈥
webbench.c:77: warning: unused parameter 鈥榮ignal鈥
cc -Wall -ggdb -W -O -o webbench webbench.o
ctags *.c
install -s webbench /usr/local/bin
install -m 644 webbench.1 /usr/local/man/man1
install: cannot create regular file `/usr/local/man/man1': No such file or directory
make: *** [install] Error 1
[root@node1 webbench-1.5]# mkdir /usr/local/man
[root@node1 webbench-1.5]# mkdir /usr/local/man/man1
[root@node1 webbench-1.5]# make &&make install
make: Nothing to be done for `all'.
install -s webbench /usr/local/bin
install -m 644 webbench.1 /usr/local/man/man1
install -d /usr/local/share/doc/webbench
install -m 644 debian/copyright /usr/local/share/doc/webbench
install -m 644 debian/changelog /usr/local/share/doc/webbench
usage()
[root@node1 data]# webbench --help
webbench [option]... URL
-f|--force Don't wait for reply from server.
-r|--reload Send reload request - Pragma: no-cache.
-t|--time <sec> Run benchmark for <sec> seconds. Default 30.
-p|--proxy <server:port> Use proxy server for request.
-c|--clients <n> Run <n> HTTP clients at once. Default one.
-9|--http09 Use HTTP/0.9 style requests.
-1|--http10 Use HTTP/1.0 protocol.
-2|--http11 Use HTTP/1.1 protocol.
--get Use GET request method.
--head Use HEAD request method.
--options Use OPTIONS request method.
--trace Use TRACE request method.
-?|-h|--help This information.
-V|--version Display program version.
执行命令:webbench -c 10 http://www.baidu.com
命令就是用10个客户端并发百度网站30秒,但是在执行的命令报错了:Invalid URL syntax - hostname don't ends with '/'
。解决办法就是在url后加个“/”
执行结果反馈内容:
[root@node1 data]# webbench -c 10 -t 30 http://www.baidu.com/
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://www.baidu.com/
10 clients, running 30 sec.
Speed=2254 pages/min, 4188293 bytes/sec.
Requests: 1110 susceed, 17 failed.
其他一些压测工具:
http_load
apache bench
seige
wrk