Webbench 源码分析 阅读笔记

一.简介

Webbench是有名的网站压力测试工具,它是由 Lionbridge公司开发。

Webbech能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。webBech的标准测试可以向我们展示服务器的 两项 内容:每秒钟相应请求数和每秒钟传输数据量。webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,JAVA,CGI)进 行测试的能力。还有就是他支持对含有SSL的安全网站例如电子商务网站进行静态或动态的性能测试。

Webbench最多可以模拟3万个并发连接去测试网站的负载能力,其源码仅仅500行左右。

二.源码解读

源码一共包含两个源文件:socket.c 和 webbench.c 。

1. socket.c

本文件仅包含一个Socket函数:

int Socket(const char *host, int clientPort)
{
/*
 * 以host和clientPort构成一对TCP的套接字(host支持域名)
 * 创建失败返回-1,成功返回一个sockt描述符
 *
 * 涉及的知识点:
 * inet_addr:若字符串有效则将字符串转换为32位二进制
 * 网络字节序的IPV4地址,否则为INADDR_NONE;
 * gethostbyname:返回对应于给定主机名的包含主机名字
 * 和地址信息的hostent结构指针;
 * htons:将一个无符号短整型(s)的主机数值(h)转换为网络字节顺序(n);
 * socket:创建套接字
 * connect:连接到相应的主机
 */
    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;
}

2.webbench.c

在webbench.c中,包含了下面几个函数:

    static void alarm_handler(int signal);
    static void usage(void);
    static void build_request(const char *url);
    static int bench(void);
    static void benchcore(const char *host, const int port, const char *req);
    int main(int argc, char *argv[]);

- Webbench工作流程:

  1. 进入main函数,解析命令行参数;

  2. 调用build_request()函数,构造http request信息;

  3. 调用bench()函数,根据client大小fork子进程;

  4. 子进程调用benchcore()函数进行测试,挂接信号处理函数alarm_handler,将结果写入管道。

  5. 主进程从管道读取消息,并输出到stdout。

下面逐个部分进行分析:

- 全局变量

/* values */
/* 超时标识,由命令行参数-t指定,当被设置为1时,所有子进程退出
 * volatile:
 *    - 让系统总是从内存读取数据,
 *    - 告诉编译器不要做任何优化,
 *    - 变量会在程序外被改变
 */
volatile int timerexpired=0; 
int speed=0; //子进程成功得到服务器响应的总数
int failed=0; //子进程请求失败总数
int bytes=0; //读取到的字节总数
/* globals */
int http10=1; /* 0 - http/0.9, 1 - http/1.0, 2 - http/1.1 */ //HTTP协议版本
/* Allow: GET, HEAD, OPTIONS, TRACE */
#define METHOD_GET 0
#define METHOD_HEAD 1
#define METHOD_OPTIONS 2
#define METHOD_TRACE 3
#define PROGRAM_VERSION "1.5"
int method=METHOD_GET; //HTTP请求方法,默认为GET
int clients=1; //并发数,即子进程个数,默认为1,可以由命令行参数-c指定
int force=0; //是否等待从服务器获取数据,0表示等待
int force_reload=0; //是否使用cache,0为使用
int proxyport=80; //代理服务器端口,默认为80
char *proxyhost=NULL; //代理服务器IP,默认为NULL
/*
 * 执行时间,默认为30秒,可由命令行参数-t指定,
 * 当子进程执行时间超过这个秒数之后,
 * 发送 SIGALRM 信号,将 timerexpired 设置为 1,
 * 让所有子进程退出 
 */
int benchtime=30; 
/* internal */
int mypipe[2]; //创建管道(半双工),用于父子进程间通信
char host[MAXHOSTNAMELEN]; //服务器IP
#define REQUEST_SIZE 2048
char request[REQUEST_SIZE]; //HTTP请求信息

/* 命令行的选项配置表,参见man文档:man getopt_long */
static const struct option long_options[]=
{
 {
  "force",no_argument,&force,1},
 {
  "reload",no_argument,&force_reload,1},
 {
  "time",required_argument,NULL,'t'},
 {
  "help",no_argument,NULL,
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值