服务器压力测试_服务器调制、调试和测试 - 压力测试

有压力测试程序有很多种实现方式,比如I/O复用方式,多线程、多进程并发编程方式,以及这些方式的结合使用。不过单纯的I/O复用方式的施压程度是最高的,因为线程和进程的调度本身也要占用一定的CPU时间的。因此,我们将使用epoll来实现一个通用的服务器压力测试程序,示例代码如下:

d123839ca60790d64ccd766c2b1b3da6.png
#include #include #include #include #include #include #include #include #include #include #include /*每个客户连接不停地向服务器发送这个请求*/static const char* request = "GET http://localhost/index.html HTTP/1.1Connection:keep-alivexxxxxxxxxxxxxx";int setnonblocking(int fd){    int old_option = fcntl(fd, F_GETFL);    int new_option = old_option | O_NONBLOCK;    fcntl(fd, F_SETFL, new_option);    return old_option;}void addfd(int epoll_fd, int fd){    epoll_event event;    event.data.fd = fd;    event.events = EPOLLOUT|EPOLLET|EPOLLERR;    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event);    setnonblocking(fd);}/*向服务器写入len字节的数据*/bool write_nbutes(int sockfd, const char* buffer, int len){    int bytes_write = 0;    printf("write out %d bytes to socket %d", len, sockfd);    while(1){        bytes_write = send(sockfd, buffer, len, 0);        if(bytes_write == -1){            return false;        }        else if(bytes_write == 0){            return false;        }        len -= bytes_write;        buffer = buffer + bytes_write;        if(len < 0){            return true;        }    }}/*从服务器读取数据*/bool read_once(int sockfd, char* buffer, int len){    int bytes_read = 0;    memset(buffer, '0', len);    bytes_read = recv(sockfd, buffer, len, 0);    if(bytes_read == -1){        return false;    }    else if(bytes_read == 0){        return false;    }    printf("read in %d bytes from socket %d with content: %s",         bytes_read, sockfd, buffer);        return true;}/*向服务器发起num个TCP连接,我们可以通过改变num来调整压力测试*/void start_conn(int epoll_fd, int num, const char* ip, int port){    int ret = 0;    struct sockaddr_in address;    bzero(&address, sizeof(address));    address.sin_family = AF_INET;    inet_pton(AF_INET, ip, &address.sin_addr);    address.sin_port = htons(port);    for(int i = 0; i < num; ++i){        sleep(1);        int sockfd = socket(PF_INET, SOCK_STREAM, 0);        printf("create 1 sock");        if(sockfd < 0){            continue;        }        if(connect(sockfd, (struct sockaddr*)&address, sizeof(address)) == 0){            printf("build connection %d", i);            addfd(epoll_fd, sockfd);        }    }}void close_conn(int epoll_fd, int sockfd){    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sockfd, 0);    close(sockfd);}int main(int argc, char const *argv[]){    assert(argc == 4);    int epoll_fd = epoll_create(100);    start_conn(epoll_fd, atoi(argv[3]), argv[1], atoi(argv[2]));    epoll_event events[10000];    char buffer[2048];    while(1){        int fds = epoll_wait(epoll_fd, events, 10000, 2000);        for(int i = 0; i< fds; ++i){            int sockfd = events[i].data.fd;            if(events[i].events & EPOLLIN){                if(!read_once(sockfd, buffer, 2048)){                    close_conn(epoll_fd, sockfd);                }                struct  epoll_event event;                event.events = EPOLLOUT | EPOLLET | EPOLLERR;                event.data.fd = sockfd;                epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sockfd, &event);            }            else if(events[i].events & EPOLLOUT){                if(!write_nbutes(sockfd, request, strlen(request))){                    close_conn(epoll_fd, sockfd);                }                struct  epoll_event event;                event.events = EPOLLIN | EPOLLET | EPOLLERR;                event.data.fd = sockfd;                epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sockfd, &event);            }            else if(events[i].events & EPOLLERR){                close_conn(epoll_fd, sockfd);            }        }    }    return 0;}

下面考虑将使用该压力程序测试(名为stress_test)来测试进程池和线程池 - 用线程池实现的简单Web服务器一文中所描述的Web服务器的稳定性,我们先在一台机器上运行websrv,然后在另一台机器上运行stress_test,向websrv服务器发起1000个连接,具体操作如下:

$ ./websrv 10.0.0.199 12345 #启动web server,监听端口12345

$ ./stress_test 10.0.0.199 12345 1000

如果websrv服务器程序足够稳定,那么websrv和stress_test这两个程序将一直运行下去,并不断交换数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值