nginx 网络模型惊群问题

296 天前
 0littleboy

最近在写一个网络模型,仿写了 nginx ,但是用的是多线程而非多进程

遇到一个问题,多个 epoll 线程只有一个在工作,问题大概是处理 epoll 惊群引起的:

  1. 所有线程争抢 accept 锁
  2. 抢到锁的线程监听 listenfd
  3. 当所有线程都进入 epoll_wait 后
  4. 只有监听 listenfd 的线程会被唤醒
  5. 唤醒的线程处理完任务后,开始重复 1 的过程,这时别的线程处于 epoll_wait ,当然只有该线程能抢到继续 accept 的权利

如何能让其他线程知道自己可以争抢锁了呢

974 次点击
所在节点    程序员
6 条回复
victorc
296 天前
你搞错了呗,可以看看 memcache 的代码

accept 的 fd 用一个单独的 epoll
worker 线程人手一个 epoll ,把一个 pipe 也放到这个 epoll 里面监视
收到新连接,选择一个 worker 线程,把 fd 通过 pipe 写过去,
julyclyde
296 天前
我一直以为惊群是古代内核的 bug
现在还有这问题??
0littleboy
295 天前
@julyclyde #2 accept 惊群随着内核的更新确实解决了,但是 epoll 还是存在惊群
ihciah
295 天前
一个解决办法是每个 thread 创建自己的 listener socket ,还有一个办法是放弃 epoll + syscall ,用 io_uring 。
或者使用多线程+单 epoll 的形式,类似你说的单个线程陷入 epoll_wait ,其他线程等待该线程——线程等待可以用 futex 之类的东西做,也可以直接用锁,底层实现也是 futex 。
Perfect1zsh1t
295 天前
muduo 网络库的实现思路是,主 epoll 负责接收连接请求,各个其他线程的子 epoll 负责拿到这个 fd 进行 accept 操作。主 epoll 向其他线程的分发操作采用轮询的方式均匀分发给每个线程。
holy5pb
295 天前
小白问个与原题无关的,如果要系统的学习网络知识,达到 OP 这样能仿写 ng 的水平,需要哪些知识储备呢,有没有推荐的教程或书籍

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/957631

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX