许多linux/unix编程书籍和教程都谈到了"Thundering Herd Problem",当多个线程或for在select()调用上被阻塞,等待侦听套接字的可读性时,就会发生这种情况。当连接进入时,所有线程和fork都被唤醒,但只有一个线程成功调用了"accept()“。同时,大量的cpu时间无缘无故地被浪费在唤醒所有线程/ for上。
我注意到了一个project,它在linux内核中提供了这个问题的“修复”,但这是一个非常旧的补丁。
我认为有两种变体;一种是每个fork都选择(),然后接受(),另一种是直接接受()。
现代的unix/linux内核在这两种情况下还是只有"select()然后accept()“版本的雷群问题?
发布于 2014-04-11 09:34:23
多年来,大多数unix/linux内核将响应序列化为accept(2)s,换句话说,如果多个线程对单个打开的文件描述符的accept(2)阻塞,则只有一个线程被唤醒。
OTOH,许多(如果不是所有的)内核在你描述的选择-接受模式中仍然有雷鸣般的羊群问题。
我已经编写了一个简单的脚本( https://gist.github.com/kazuho/10436253 )来验证这个问题的存在,并发现这个问题存在于Linux2.6.32和Darwin12.5.0(OSX10.8.5)上。
发布于 2010-02-07 07:23:19
这是一个非常古老的问题,而且在很大程度上已经不存在了。Linux内核(在过去几年中)在处理和路由数据包的方式上有了许多变化,并包括许多优化,以确保低延迟和公平性(即最小化饥饿)。
也就是说,仅通过其API,select系统就有许多可伸缩性问题。当您有大量的文件描述符时,select调用的成本非常高。这主要是因为必须构建、检查和维护传入和传出系统调用的FD集。
现在,异步IO的首选方式是使用epoll。API要简单得多,并且可以很好地扩展到各种类型的负载(许多连接、大量吞吐量等)。
发布于 2012-11-27 04:55:37
我最近看到测试了一个场景,其中多个线程在侦听unix域套接字上轮询,然后接受连接。所有线程都使用poll()系统调用唤醒。
这是linux内核的自定义构建,而不是发行版构建,所以可能有一个内核配置选项来更改它,但我不知道这是什么。
我们没有尝试epoll。
https://stackoverflow.com/questions/2213779
复制相似问题