云计算百科
云计算领域专业知识百科平台

2.1.3服务器百万并发

依托上节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(&current,NULL);

printf("accept finshed:%d\\n",clientfd);
int time_used = TIME_SUB_MS(current,begin);
memcpy(&begin,&current,sizeof(struct timeval));

printf("accept finshed:%d,time_used:%d\\n",clientfd,time_used);
}

gettimeofday(&current,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

赞(0)
未经允许不得转载:网硕互联帮助中心 » 2.1.3服务器百万并发
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!