nginx 网络模型惊群问题

2023-07-18 11:10:56 +08:00
 0littleboy

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

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

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

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

1198 次点击
所在节点    程序员
6 条回复
victorc
2023-07-18 12:24:23 +08:00
你搞错了呗,可以看看 memcache 的代码

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

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

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

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

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

© 2021 V2EX