首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 服务器 > 云计算 >

怎么提高服务器的性能

2013-11-09 
如何提高服务器的性能本帖最后由 yts2dx 于 2013-10-14 20:33:15 编辑首先介绍一下服务器的基本配置:两个

如何提高服务器的性能
本帖最后由 yts2dx 于 2013-10-14 20:33:15 编辑 首先介绍一下服务器的基本配置:两个 Intel(R) Xeon(R) CPU E7- 4807  @ 1.87GHz 的cpu,32G的内存。
在下做的是一个转发服务器,服务器接收1000条的连接,这1000条连接向服务器发送数据,每秒512B的数据量。服务器接收到数据后,转发到若干个客户端。
小弟是用epoll机制写的。现在的问题是客户端接收到的数据存在延迟,通过netstat命令发现数据大量缓存在服务器的接收缓冲区中。而发送缓冲区中基本没有数据。
如果服务器只是接收数据,而不进行转发,服务器的接收缓冲区中不会有数据。
主要涉及函数如下:

void *EpollThread(void *ptr){

        int listenq = 1024;

        int listenfd, connfd, kdpfd, nfds, n, nread, curfds,acceptCount = 0;
        struct sockaddr_in servaddr, cliaddr;
        socklen_t socklen = sizeof(struct sockaddr_in);
        struct epoll_event ev;
        struct epoll_event events[MAXEPOLLSIZE];
        struct rlimit rt;
        char buf[MAXLINE];

        /* 设置每个进程允许打开的最大文件数 */
        rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
        if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
        {
                perror("setrlimit error");
        }
        
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
        servaddr.sin_port = htons (EPOLLCLIENT_PORT);

        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listenfd == -1) {
                perror("can't create socket file");
        }

        int opt = 1;
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) == -1)
        {
                perror("bind error");
        }
        if (listen(listenfd, listenq) == -1)
        {
                perror("listen error");
        }
        /* 创建 epoll 句柄,把监听 socket 加入到 epoll 集合里 */
        kdpfd = epoll_create(MAXEPOLLSIZE);
        ev.events = EPOLLIN;
        ev.data.fd = listenfd;
        if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listenfd, &ev) < 0)
        {
                fprintf(stderr, "epoll set insertion error: fd=%d\n", listenfd);
        }
        curfds = 1;
        //curfds = 10000;

        printf("epollserver startup,port %d, max connection is %d, backlog is %d\n", EPOLLCLIENT_PORT, MAXEPOLLSIZE, listenq);

        for (;;)
        {
                /* 等待有事件发生 */
                //nfds = epoll_wait(kdpfd, events, curfds, -1);
                nfds = epoll_wait(kdpfd, events, curfds, 10000);
                if (nfds == -1)
                {
                        perror("epoll_wait");
                        continue;


                }
                //int tempint=0;
                /* 处理所有事件 */
                for (n = 0; n < nfds; ++n)
                {
                        if (events[n].data.fd == listenfd)
                        {
                                //printf("%d",nfds);
                                connfd = accept(listenfd, (struct sockaddr *)&cliaddr,&socklen);
                                if (connfd < 0)
                                {
                                        perror("accept error");
                                        continue;
                                }

                                sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
                                ConnectionCount++;

                                printf("维持连接数:%d %s ConnectionCount:%d\n", ++acceptCount, buf,ConnectionCount);
                                if (curfds >= MAXEPOLLSIZE) {
                                        fprintf(stderr, "too many connection, more than %d\n", MAXEPOLLSIZE);
                                        close(connfd);
                                        continue;
                                }
                                if (setnonblocking(connfd) < 0) {
                                        perror("setnonblocking error");
                                }
                                ev.events = EPOLLIN | EPOLLET;
                                ev.data.fd = connfd;
                                if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, connfd, &ev) < 0)


                                {
                                        fprintf(stderr, "add socket '%d' to epoll failed: %s\n", connfd, strerror(errno));
                                }
                                curfds++;
                                continue;
                        }
                        //处理来自客户端的数据
                        if (handle(events[n].data.fd) < 0) {

                                epoll_ctl(kdpfd, EPOLL_CTL_DEL, events[n].data.fd,&ev);
                                curfds--;
                        }
                }
        }

        close(listenfd);
}

//处理数据接收
int handle(int connfd) {

        int nread1,nread2;
        char buf_size[2];
        char buf[MAXLINE];
        nread1 = read(connfd,buf_size,2);
        //printf("Test Point 1:the len of stream is %d\n",getLenOfStream(buf_size));
        int lenOfStream = getLenOfStream(buf_size);
        nread2 = read(connfd, buf, lenOfStream);//读取客户端socket流

        //cout<<"lenOfStream:"<<lenOfStream<<" nread1:"<<nread1<<" nread2:"<<nread2<<endl;

        if (nread1 == 0 || nread2 == 0) {
                printf("client close the connection\n");
                close(connfd);
                ConnectionCount--;
                return -1;
        }
        if (nread1 < 0 || nread2 < 0) {

                if(errno == EAGAIN)
                {

                   perror("read error");
                   close(connfd);
                   ConnectionCount--;
                   return -1;
                 }
                 else return 0;
        }
        //cout<<connfd<<endl;
        //printf("Test Point 2,print buf:%s\n",buf);
        writeDataToFile(buf,lenOfStream);  //将数据写入文件


        char carId[20]="";
        getCarIdFromBuf(buf,carId);

        //findCarid(buf,carId);
        printf("carid is :%s\n",carId);


        cout<<"len:"<<lenOfStream<<endl;
        //sleep(1);
        CountCaridRec(carId);
        forwardInfo(buf_size,buf,carId,lenOfStream);//向监控端转发来自CAN的数据

        //cout<<"len:"<<lenOfStream<<endl;
        //convertData(buf,lenOfStream);//对数据进行解析

        char tcarid[20];
        int tcartype,tdatatype;
        char tdatetime[30] = "";
        int tempDetail[4]={64,8,8,56};
        getPackageInfo(convertData(buf,lenOfStream),tempDetail,tcarid,tcartype,tdatatype,tdatetime);
        cout<<tdatetime<<endl;

        //usleep(10000);
        return 0;
}



小弟深知还有许多地方没有考虑到,希望各位大神给点思路,指明一下方向。
[解决办法]
每次堆上申请内存然后用来read
新开一个缓存队列,讲read的数据放入其中,然后继续read,read就只做read这一个事情。
使用专门线程来进行处理缓存队列,在其中尽心“writeDataToFile(buf,lenOfStream);  //将数据写入文件”之类的处理,完了后释放申请的内存。

如果还嫌性能不够,使用专门的内存管理来进行内存重复利用。

热点排行