V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0littleboy
V2EX  ›  程序员

nginx 网络模型惊群问题

  •  
  •   0littleboy · 284 天前 · 956 次点击
    这是一个创建于 284 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    6 条回复    2023-07-19 10:20:13 +08:00
    victorc
        1
    victorc  
       284 天前
    你搞错了呗,可以看看 memcache 的代码

    accept 的 fd 用一个单独的 epoll
    worker 线程人手一个 epoll ,把一个 pipe 也放到这个 epoll 里面监视
    收到新连接,选择一个 worker 线程,把 fd 通过 pipe 写过去,
    julyclyde
        2
    julyclyde  
       284 天前
    我一直以为惊群是古代内核的 bug
    现在还有这问题??
    0littleboy
        3
    0littleboy  
    OP
       284 天前
    @julyclyde #2 accept 惊群随着内核的更新确实解决了,但是 epoll 还是存在惊群
    ihciah
        4
    ihciah  
       284 天前
    一个解决办法是每个 thread 创建自己的 listener socket ,还有一个办法是放弃 epoll + syscall ,用 io_uring 。
    或者使用多线程+单 epoll 的形式,类似你说的单个线程陷入 epoll_wait ,其他线程等待该线程——线程等待可以用 futex 之类的东西做,也可以直接用锁,底层实现也是 futex 。
    Perfect1zsh1t
        5
    Perfect1zsh1t  
       283 天前
    muduo 网络库的实现思路是,主 epoll 负责接收连接请求,各个其他线程的子 epoll 负责拿到这个 fd 进行 accept 操作。主 epoll 向其他线程的分发操作采用轮询的方式均匀分发给每个线程。
    holy5pb
        6
    holy5pb  
       283 天前
    小白问个与原题无关的,如果要系统的学习网络知识,达到 OP 这样能仿写 ng 的水平,需要哪些知识储备呢,有没有推荐的教程或书籍
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2959 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:07 · PVG 22:07 · LAX 07:07 · JFK 10:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.