龙空技术网

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

吃泡菜的鱼 101

前言:

而今我们对“服务器的测试”大概比较重视,朋友们都需要知道一些“服务器的测试”的相关资讯。那么小编同时在网摘上收集了一些对于“服务器的测试””的相关文章,希望小伙伴们能喜欢,你们一起来学习一下吧!

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

#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <unistd.h>#include <sys/types.h>#include <sys/epoll.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>/*每个客户连接不停地向服务器发送这个请求*/static const char* request = "GET  HTTP/1.1\r\nConnection:keep-alive\r\nxxxxxxxxxxxxxx";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\n", 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\n",         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\n");        if(sockfd < 0){            continue;        }        if(connect(sockfd, (struct sockaddr*)&address, sizeof(address)) == 0){            printf("build connection %d\n", 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这两个程序将一直运行下去,并不断交换数据。

标签: #服务器的测试