惊群:
多个进程或者线程阻塞等待同一个事件,当事件到来,多线程或者多进程同时被唤醒,只有一个线程或进程获得资源。
通俗点说,往鸡群里仍一颗稻谷,鸡群争抢,只有一个成功,其它失败。
现象:
火焰图观察 accept,或者用 strace 命令观察底层调用。
结果:
线程或进程频繁切换,会导致系统资源损耗。
解决方案:
1、代码同步加锁(参考 nginx 源码)。
2、设置 socket 属性 SO_REUSEPORT (Linux 系统内核层面解决,这个方案简单,参考 nginx 这个属性设置)
原理:
当用 epoll 事件处理高并发事件模型时候,多个进程或线程 epoll_wait 会阻塞等待网络事件,当有新的 client connect 进来,epoll_wait 会同时被会唤醒争抢这个链接资源,然后调用 accept 处理,争抢资源失败的 accept 会返回 EAGAIN。
测试:
源码 server 是 epoll 事件模型,client 用 telnet 即可。
后记:
以上只是记录了些学习心得避免遗忘,参考了不少帖子(下面)。现在很多 linux 服务器项目不会直接用 epoll 模型了,因为有很多跨平台的开源解决方案可以选择:libev, libuv, libevent, 最近笔者换了 mbp 本子发现 epoll 竟然跑不起来,macOs 下是 kqueue,还好项目网络底层用的是 libev,安装一下,项目又能跑起来了,酸爽~。虽然这些开源项目都很不错,但是对一个有追求的码农,掌握它们运行原理还是很有必要的。
参考:
一个epoll惊群导致的性能问题
Linux惊群效应详解
Linux 最新SO_REUSEPORT特性