Linux(服务器编程):百万并发服务器系统参数调优( 五 )

< MAX_EPOLL_EVENTS;i ++) { if (reactor->events[i].status == 0) { break;}} if (i == MAX_EPOLL_EVENTS) { printf("%s: max connect limit[%d]\n", __func__, MAX_EPOLL_EVENTS); break;}int flag = 0; if ((flag = fcntl(clientfd, F_SETFL, O_NONBLOCK)) < 0) { printf("%s: fcntl nonblocking failed, %d\n", __func__, MAX_EPOLL_EVENTS); break;}nty_event_set(nty_event_add(reactor->epfd, EPOLLIN,} while (0); printf("new connect [%s:%d][time:%ld], pos[%d]\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), reactor->events[i].last_active, i); return 0;} int init_sock(short port) { int fd = socket(AF_INET, SOCK_STREAM, 0); fcntl(fd, F_SETFL, O_NONBLOCK); struct sockaddr_in server_addr; memset( server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); bind(fd, (struct sockaddr*) if (listen(fd, 20) < 0) { printf("listen failed : %s\n", strerror(errno)); } return fd;} int ntyreactor_init(struct ntyreactor *reactor) { if (reactor == NULL) return -1; memset(reactor, 0, sizeof(struct ntyreactor)); reactor->epfd = epoll_create(1); if (reactor->epfd <= 0) { printf("create epfd in %s err %s\n", __func__, strerror(errno)); return -2; } reactor->events = (struct ntyevent*)malloc((MAX_EPOLL_EVENTS) * sizeof(struct ntyevent)); if (reactor->events == NULL) { printf("create epfd in %s err %s\n", __func__, strerror(errno));close(reactor->epfd); return -3; } return 0;} int ntyreactor_destroy(struct ntyreactor *reactor) { close(reactor->epfd); free(reactor->events);} int ntyreactor_addlistener(struct ntyreactor *reactor, int sockfd, NCALLBACK *acceptor) { if (reactor == NULL) return -1; if (reactor->events == NULL) return -1; nty_event_set( nty_event_add(reactor->epfd, EPOLLIN,return 0;} int ntyreactor_run(struct ntyreactor *reactor) { if (reactor == NULL) return -1; if (reactor->epfd < 0) return -1; if (reactor->events == NULL) return -1; struct epoll_event events[MAX_EPOLL_EVENTS+1]; int checkpos = 0, i; while (1) { long now = time(NULL); for (i = 0;i < 100;i ++, checkpos ++) { if (checkpos == MAX_EPOLL_EVENTS) {checkpos = 0;} if (reactor->events[checkpos].status != 1) { continue;} long duration = now - reactor->events[checkpos].last_active; if (duration >= 60) {close(reactor->events[checkpos].fd); printf("[fd=%d] timeout\n", reactor->events[checkpos].fd);nty_event_del(reactor->epfd,}} int nready = epoll_wait(reactor->epfd, events, MAX_EPOLL_EVENTS, 1000); if (nready < 0) { printf("epoll_wait error, exit\n"); continue;} for (i = 0;i < nready;i ++) { struct ntyevent *ev = (struct ntyevent*)events[i].data.ptr; if ((events[i].events} if ((events[i].events}} }} int main(int argc, char *argv[]) { unsigned short port = SERVER_PORT; if (argc == 2) {port = atoi(argv[1]); }struct ntyreactor *reactor = (struct ntyreactor*)malloc(sizeof(struct ntyreactor)); ntyreactor_init(reactor);int listened[LISTEN_PORT_COUNT]; int i = 0; for(i = 0; i < LISTEN_PORT_COUNT; ++i){listened[i] = init_sock(port + i);ntyreactor_addlistener(reactor, listened[i], accept_cb);}ntyreactor_run(reactor);ntyreactor_destroy(reactor);for(i = 0; i < LISTEN_PORT_COUNT; ++i){close(listened[i]);} return 0;}

  • 第二步:
    • 修改客户端程序mul_port_client_epoll.c , 将其MAX_PORT宏修改为5即可 , 修改完成之后 , 其就会向5个服务端都发起连接
    • 修改完成之后重新编译
#define MAX_PORT 5
Linux(服务器编程):百万并发服务器系统参数调优文章插图
备注(必看)
  • 此处出错的场景在实际开发中是不会出现的 , 因为在实际生活中 , 不会出现一个系统中有上万的客户端(IP都一致) , 因此出现了这种“五元组”组合用尽的情况
  • 在实际中 , 每个客户端的IP地址都是不同的 , 因此它们的“五元组”类型都是不同的 , 因此就不会出现这种因为端口被用完从而导致“五元组”组合被用尽的情况
  • 修改完成之后进行下面的第3次测试
五、第3次测试测试如下
  • 左侧运行服务端程序reactor(111.229.177.161:8888) , 右侧运行两个客户端程序mul_port_client_epoll去连接服务器
  • 效果如下:
    • 左侧服务端持续接收客户端的连接
    • 右侧两个客户端向服务端发起连接 , 但是当两个客户端都连接到64999的时候 , 客户端不动了 , 阻塞了(程序没有报错 , 也没有退出)
    • 左侧服务端也跟着阻塞了(程序没有报错 , 也没有退出)
    • 过了一小会之后 , 客户端显示连接超时 , 然后程序退出

Linux(服务器编程):百万并发服务器系统参数调优文章插图
Linux(服务器编程):百万并发服务器系统参数调优文章插图
原因分析
  • nf_conntrack_max限制了每一个程序可以建立的TCP的连接的最大数目(是连接数目 , 而不是套接字描述符的个数)
解决方案