如何提高服务器的性能
本帖最后由 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;
}