依托上节reactor实现的tcp server,再通过虚拟机创建三个客户端连接这台tcp server。
在运行时服务器出现问题:
这是由于在执行accept逻辑时,accept返回的clientfd值为-1,此时conn_list数组下标访问失败,因此需要先判断clientfd是否合理:
int clientfd=accept(fd,(struct sockaddr*)&clientaddr,&len);
///printf("accept finshed:%d\\n",clientfd);
if(clientfd<0){
printf("accpet errno:%d—-> %s\\n",errno,strerror(errno));
return -1;
}
而客户端出现如下问题:
这个问题可通过ulimt -a 指令查看open files数量,并通过指令ulimit -n 1048576
修改数量:
修改完后:
也可以通过 sudo vim /etc/security/limits.conf,在文件末尾添加以下配置:
修改完后发现服务器也存在相同的问题:
同样使用指令ulimit -n 1048576进行修改
如果通过上述操作客户端还出现上述问题,是由于ubuntu(16,客户端版本)版本导致:可能需要在vim /etc/sysctl.conf 当中修改这一段:
再执行sudo sysctl -p即可
代码在运行一段时间后,出现问题:
这是因为每个tcp连接是由一个五元组唯一确定的[源ip,源端口,目的ip,目的端口,传输层协议]
此时源端口不够,导致出现问题,因此,可以同时监听多个端口(从一个端口到20个端口):
for(i=0;i<MAX_PORTS;i++){
int sockfd=Init_server(port+i);
conn_list[sockfd].fd=sockfd;
conn_list[sockfd].r_action.recv_callback=accept_cb;
set_event(sockfd,EPOLLIN,1);
}
为了避免打印信息降低速率,可以每一千次连接才打印一条信息,并获取这一千条连接耗费的时间:
if((clientfd%1000)==0){
struct timeval current;
gettimeofday(¤t,NULL);
printf("accept finshed:%d\\n",clientfd);
int time_used = TIME_SUB_MS(current,begin);
memcpy(&begin,¤t,sizeof(struct timeval));
printf("accept finshed:%d,time_used:%d\\n",clientfd,time_used);
}
gettimeofday(¤t,NULL):获取系统时间。
TIME_SUB_MS(current,begin):两个时间的差值。
memcy:将本次current时间拷贝到begin当中,覆盖旧值。
如果客户端出现:
其实是正常的,在recv逻辑中添加EAGANIN无视该错误:
if (errno == EINTR||errno == EAGAIN) continue;
客户端出现killed错误:这是由于cpu占用过高,系统将进程终止。
服务器出现killed错误:当cpu占用过高,物理内存 + SWAP 全部耗尽时,内核选择评分最高的进程终止。
如果内存不足,可以通过调高虚拟机内存或者修改swap空间;
Swap 空间可以是硬盘上的一个分区,也可以是文件形式存在于硬盘上。它本质上是一块存储区域,用来模拟内存, 以便在物理内存(RAM)不够用时,协助操作系统进行内存管理。
解法:可以调大虚拟机内存,但是也可以通过扩充swap空间也能达到目的。
例如将swap扩充4g:
sudo dd if=/dev/zero of=/extraswap bs=1G count=4
sudo mkswap /extraswap
sudo swapon /extraswap
这样在物理内存不够用的情况下可以继续使用swap空间。
在调试运行服务器的时候出现如下情况:
而内存情况似乎正常:
但是accept finshed输出停止,大约一分钟左右后服务器突然断开连接了,导致客户端连接超时。
核心问题是连接跟踪表耗尽引发内核丢包,导致TCP连接被迫重置。
需要修改连接跟踪表大小(其实跟16版本修改net.nf_conntrack_max一样):
1.通过指令sysctl net.nf_conntrack_max查看连接跟踪表大小。
2.再通过sudo sysctl -w net.nf_conntrack_max=1048576进行修改。
通过解决以上问题,成功实现了百万并发的连接:
并发量主要看:
网络io,qps(一秒钟可以处理多少请求),时延。
本小节主要是运行调试百万并发服务器,并进行错误排查。
https://github.com/0voice
评论前必须登录!
注册