zoukankan      html  css  js  c++  java
  • 用EPOLL进行压力测试

    在以前的博客中提到的一个服务端,在以前压力测试的过程中,发现单核CPU最多能达到1000TPS

    还以为是服务端性能不够好,所以一直想着怎么去优化它。

    但优化的思路明显不多,所以就考虑换一种压力测试的方法,事实证明这个想法是对的。

    以前的压力测试方法 :

    for((i=0;i<$3;i++));do
    
           for((j=0;j<$4;j++));do
                cmd="./client $1 $2 4 $a $a $a $a" 
                echo `time $cmd`
    
           done&
    
    done

    思路是用多进程来实现并发,代码如上所示;

    现在的压力测试方法:

    //客户端程序    
    
    /******* 客户端程序 client.c ************/    
    #include  <stdio.h>   
    #include  <stdlib.h>   
    #include <sys/types.h>   
    #include <sys/socket.h>   
    #include  <string.h>   
    #include  <netdb.h>   
    #include <netinet/in.h>   
    #include <errno.h>   
    #include <arpa/inet.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/epoll.h>
    
    
    static struct sockaddr_in server_addr;    
    static int epoll_fd;
    static int currency,total_req,total_read;    
    static struct epoll_event* events;
    
    int setnonblock(int fd)
    {
            int flags;
            flags = fcntl(fd, F_GETFL);
            flags |= O_NONBLOCK;
            fcntl(fd, F_SETFL, flags);
    }
    
    void new_conn()
    {
            if(--total_req < 0)return;
            int sockfd;
            /* 客户程序开始建立 sockfd描述符 */    
            if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)    
            {    
                    fprintf(stderr,"Socket Error:%sa
    ",strerror(errno));    
                    return ;
            }    
            setnonblock(sockfd);
    
            //让epoll接管
            struct epoll_event event;
            event.data.fd=sockfd;
            event.events = EPOLLOUT|EPOLLIN;
            epoll_ctl(epoll_fd,EPOLL_CTL_ADD, sockfd,&event);
    
            /* 客户程序发起连接请求 */    
            if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)    
            {    
                    if(errno == EINPROGRESS)
                            return;
                    fprintf(stderr,"Connect Error:%sa
    ",strerror(errno));    
                    return;
            }    
    
    
    }
    int main(int argc, char *argv[])    
    {    
            struct hostent *host;    
            if((host=gethostbyname(argv[1]))==NULL)    
            {    
                    fprintf(stderr,"Gethostname error
    ");    
                    exit(1);    
            }    
    
            int portnumber;    
            if((portnumber=atoi(argv[2]))<0)    
            {    
                    fprintf(stderr,"Usage:%s hostname portnumbera
    ",argv[0]);    
                    exit(1);    
            }    
    
            /* 客户程序填充服务端的资料 */    
            bzero(&server_addr,sizeof(server_addr));    
            server_addr.sin_family=AF_INET;    
            server_addr.sin_port=htons(portnumber);    
            server_addr.sin_addr=*((struct in_addr *)host->h_addr);    
    
            //并发数和总的请求数
            currency = atoi(argv[3]);
            total_req = total_read = currency * atoi(argv[4]);
    
            if((epoll_fd=epoll_create(1000))==-1)    
            {    
                    fprintf(stderr,"epoll create Error:%sa
    ",strerror(errno));    
                    exit(1);    
            }    
    
            events = calloc(1000,sizeof(struct epoll_event));
    
            //初始化并发数个连接
            int i;
            for(i=0;i<currency;i++)new_conn(); 
    
    
            while(1)
            {
                    fprintf(stderr,"while
    ");
                    int n,j;
                    n = epoll_wait(epoll_fd, events, 1000, -1);
                    for(j=0;j<n;j++)
                    {
                            if(events[j].events & EPOLLOUT)
                            {
                                    fprintf(stderr, "can write
    ",n);
                                    int fd = events[j].data.fd;
                                    int optval;
                                    socklen_t optlen = sizeof(optval);
                                    if(getsockopt(fd,SOL_SOCKET,SO_ERROR,&optval, &optlen) == -1)
                                    {
                                            fprintf(stderr, "getsockopt error
    ",n);
                                    } else if(optval != 0) {
                                            fprintf(stderr, "connect error
    ",n);
                                            continue;
                                    };
                                    struct epoll_event event;
                                    event.data.fd=fd;
                                    event.events = EPOLLIN;
                                    epoll_ctl(epoll_fd,EPOLL_CTL_MOD, fd,&event);
    
                                    char buffer2[100];
                                    memset(buffer2,100,0);
                                    int type,score,time;
                                    unsigned long oid;
                                    type= htonl(atoi(argv[5]));
                                    oid= htonl(atol(argv[6]));
                                    score= htonl(atoi(argv[7]));
                                    char*pass="220106aa";
                                    char*loc = buffer2;
                                    memcpy((void*)loc,(void*)(pass),8);
                                    loc+=8;
                                    memcpy((void*)loc,(void*)(&type),4);
                                    loc+=4;
                                    memcpy((void*)loc,(void*)(&oid),8);
                                    loc+=8;
                                    memcpy((void*)loc,(void*)(&score),4);
                                    write(fd, buffer2, 24);
                                    /* 连接成功了 */    
                            }
                            else if(events[j].events & EPOLLIN)
                            {
                                    fprintf(stderr, "can read
    ",n);
                                    int fd = events[j].data.fd;
                                    char buf[100];
                                    int n=read(fd,buf,100);
                                    close(fd);
                                    new_conn();
                                    if(n==-1)
                                    {
                                            fprintf(stderr,"read Error:%sa
    ",strerror(errno));    
                                            continue;
                                    }
                                    buf[n]=0;
                                    fprintf(stderr, "return %s
    ",buf);
                                    fprintf(stderr, "total_read %d
    ",total_read);
                                    if (--total_read <= 0)return;
                            }
                    }
            } 
    } 

    思路就是用单进程来测试,用EPOOL来实现并发
    代码也可下载:
    百度网盘:http://pan.baidu.com/s/1vdQqB
    github : https://github.com/hxdoit/real_time_rank/blob/master/server1-1.0/epoll.c

    性能对比:
    环境:单核CPU,两台机器,一台服务端,一台客户端
    多进程:690TPS
    EPOLL:6435TPS
    性能提高了十倍!


    分析:
    在单个机器上,使用多进程,资源消耗很大,不可能达到太大的并发
    而使用EPOLL,单进程同时监听多个socket,可以达到较高并发

  • 相关阅读:
    SpringBoot + redis + @Cacheable注解实现缓存清除缓存
    Linux常用命令
    Java8 Stream分组
    VMware CentOS网络配置(局域网其它主机可访问Linux虚拟机)
    Jenkins实现自动打包,MAVEN打包,Shell脚本启动
    Docker常用命令,Docker安装Nginx、Redis、Jenkins、tomcat、MySQL
    Postman配置Pre-request scripts预请求对请求进行AES加密
    《Java并发编程的艺术》并发编程的基础(四)
    linux shell的创建与启动
    《Java并发编程的艺术》Java内存模型(三)
  • 原文地址:https://www.cnblogs.com/hxdoit/p/3410199.html
Copyright © 2011-2022 走看看