Linux网络编程中的惊群问题

1.什么是惊群问题

​  如今网络编程中经常用到多进程或多线程模型,大概的思路是父进程创建socket,bind、listen后,通过fork创建多个子进程,每个子进程继承了父进程的socket,调用accpet开始监听等待网络连接。这个时候有多个进程同时等待网络的连接事件,当这个事件发生时,这些进程被同时唤醒,就是“惊群”。这样会导致什么问题呢?我们知道进程被唤醒,需要进行内核重新调度,这样每个进程同时去响应这一个事件,而最终只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新休眠或其他。网络模型如下图所示:

img

简而言之,惊群现象(thundering herd)就是当多个进程和线程在同时阻塞等待同一个事件时,如果这个事件发生,会唤醒所有的进程,但最终只可能有一个进程/线程对该事件进行处理,其他进程/线程会在失败后重新休眠,这种性能浪费就是惊群。

2.epoll中的惊群问题

​ 在I/O多路复用中,我会使用select/poll/epoll来使内核代替我们来监听文件描述符,那这样会导致惊群问题吗?答案是肯定的。

​ 一般只有两种情况,要么先fork() 之后创建epoll实例,要么先先创建epoll实例,之后再fork()。

​ 第一种情况:先fork再创建epoll实例,这样每一个进程都有一个epollfd,而且所有的epollfd共享监听的文件描述符,这个时候如果出现listen socket,就必定会唤醒所有的进程,造成惊群现象。

​ 第二种情况:先创建epoll实例再fork,所有的进程会对一个epollfd进行操作,容易造成错误,此外还会有负载不均衡的问题

3.解决惊群问题

​ Nginx中使用mutex互斥锁解决这个问题,具体措施有使用全局互斥锁,每个子进程在epoll_wait()之前先去申请锁,申请到则继续处理,获取不到则等待,并设置了一个负载均衡的算法(当某一个子进程的任务量达到总设置量的7/8时,则不会再尝试去申请锁)来均衡各个进程的任务量。后面深入学习一下Nginx的惊群处理过程。

posted @   xiazichengxi  阅读(65)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示
主题色彩