- 浏览: 209080 次
- 性别:
- 来自: 重庆
-
文章分类
最新评论
“据说”惊群问题已经是一个很古老的问题了,并且在大多数系统中已经得到有效解决,但对我来说,仍旧是一个比较新的概念,因此有必要记录一下。
什么是惊群
举一个很简单的例子,当你往一群鸽子中间扔一块食物,虽然最终只有一个鸽子抢到食物,但所有鸽子都会被惊动来争夺,没有抢到食物的鸽子只好回去继续睡觉,等待下一块食物到来。这样,每扔一块食物,都会惊动所有的鸽子,即为惊群。对于操作系统来说,多个进程/线程在等待同一资源是,也会产生类似的效果,其结果就是每当资源可用,所有的进程/线程都来竞争资源,造成的后果:
1)系统对用户进程/线程频繁的做无效的调度、上下文切换,系统系能大打折扣。
2)为了确保只有一个线程得到资源,用户必须对资源操作进行加锁保护,进一步加大了系统开销。
最常见的例子就是对于socket描述符的accept操作,当多个用户进程/线程监听在同一个端口上时,由于实际只可能accept一次,因此就会产生惊群现象,当然前面已经说过了,这个问题是一个古老的问题,新的操作系统内核已经解决了这一问题。
linux内核解决惊群问题的方法
对于一些已知的惊群问题,内核开发者增加了一个“互斥等待”选项。一个互斥等待的行为与睡眠基本类似,主要的不同点在于:
1)当一个等待队列入口有 WQ_FLAG_EXCLUSEVE 标志置位, 它被添加到等待队列的尾部. 没有这个标志的入口项, 相反, 添加到开始.
2)当 wake_up 被在一个等待队列上调用时, 它在唤醒第一个有 WQ_FLAG_EXCLUSIVE 标志的进程后停止。
也就是说,对于互斥等待的行为,比如如对一个listen后的socket描述符,多线程阻塞accept时,系统内核只会唤醒所有正在等待此时间的队列的第一个,队列中的其他人则继续等待下一次事件的发生,这样就避免的多个线程同时监听同一个socket描述符时的惊群问题。
根据以上背景信息,我们来比较一下常见的Server端设计方案。
方案2:主线程负责监听,通过线程池方式处理连接。(通常的方法)
方案3:主线程负责监听,客户端连接上来后由主线程分配实际的端口,客户端根据此端口重新连接,然后处理数据。
先考虑客户端单连接的情况:
方案1:每当有新的连接到来时,系统内核会从队列中以FIFO的方式选择一个监听线程来服务此连接,因此可以充分发挥系统的系能并且多线程负载均衡。对于单连接的场景,这种方案无疑是非常优越的。遗憾的是,对于select、epoll,内核目前无法解决惊群问题。(nginx对于惊群问题的解决方法)
方案2:由于只有一个线程在监听,其瞬时的并发处理连接请求的能力必然不如多线程。同时,需要对线程池做调度管理,必然涉及资源共享访问,相对于方案一来说管理成本要增加不少,代码复杂度提高,性能也有所下降。
方案3:与方案2有不少类似的地方,其优势是不需要做线程调度。缺点是增加了主线程的负担,除了接收连接外还需要发送数据,而且需要两次连接,孰优孰劣,有待测试。
再考虑客户端多连接的情况:
对于数据传输类的应用,为了充分利用带宽,往往会开启多个连接来传输数据,连接之间的数据有相互依赖性,因此Server端要想很好的维护这种依赖性,把同一个客户端的所有连接放在一个线程中处理是非常有必要的。
A、同一客户端在一个线程中处理
方案1:如果没有更底层的解决方案的话,Server则需要维护一个全局列表,来记录当前连接请求该由哪个线程处理。多线程需要同时竞争一个全局资源,似乎有些不妙。
方案2:主线程负责监听并分发,因此与单连接相比没有带来额外的性能开销。仅仅会造成主线程忙于更多的连接请求。
方案3:较单线程来说,主线程工作量没有任何增加,由于多连接而造成的额外开销由实际工作线程分担,因此对于这种场景,方案3似乎是最佳选择。
B、同一客户端在不同线程中处理
方案1:同样需要竞争资源。
方案2:没理由。
方案3:不可能。
另外:
读《UNIX网络编程》第二版的第一卷时,发现作者在第27章“客户-服务器程序其它设计方法”中的27.6节“TCP预先派生子进程服务器程序,accept无上锁保护”中提到了一种由子进程去竞争客户端连接的设计方法,用伪码描述如下:
服务器主进程:
|
服务器服务子进程:
|
初 识上述代码,真有眼前一亮的感觉,也正如作者所说,以上代码确实很少见(反正我读此书之前是确实没见过)。作者真是构思精巧,巧妙地绕过了常见的预先创建 子进程的多进程服务器当主服务进程接收到新的连接必须想办法将这个连接传递给服务子进程的“陷阱”,上述代码通过共享的倾听套接字,由子进程主动地去向内 核“索要”连接套接字,从而避免了用UNIX域套接字传递文件描述符的“淫技”。
不过,当接着往下读的时候,作者谈到了“惊群” (Thundering herd)问题。所谓的“惊群”就是,当很多进程都阻塞在accept系统调用的时候,即使只有一个新的连接达到,内核也会唤醒所有阻塞在accept上 的进程,这将给系统带来非常大的“震颤”,降低系统性能。
除了这个问题,accept还必须是原子操作。为此,作者在接下来的27.7节讲述了加了互斥锁的版本:
|
原 子操作的问题算是解决了,那么“惊群”呢?文中只是提到在Solaris系统上当子进程数由75变成90后,CPU时间显著增加,并且作者认为这是因为进 程过多,导致内存互换。对“惊群”问题回答地十分含糊。通过比较书中图27.2的第4列和第7列的内容,我们可以肯定“真凶”绝对不是“内存对换”。
“元凶”到底是谁?
仔 细分析一下,加锁真的有助于“惊群”问题么?不错,确实在同一时间只有一个子进程在调用accept,其它子进程都阻塞在了lock语句,但是,当 accept返回并unlock之后呢?unlock肯定是要唤醒阻塞在这个锁上的进程的,不过谁都没有规定是唤醒一个还是唤醒多个。所以,潜在的“惊 群”问题还是存在,只不过换了个地方,换了个形式。而造成Solaris性能骤降的“罪魁祸首”很有可能就是“惊群”问题。
崩溃了!这么说所有的锁都有可能产生惊群问题了?
似乎真的是这样,所以减少锁的使用很重要。特别是在竞争比较激烈的地方。
作者在27.9节所实现的“传递文件描述符”版本的服务器就有效地克服了“惊群”问题,在现实的服务器实现中,最常用的也是此节所提到的基于“分配”形式。
把“竞争”换成“分配”是避免“惊群”问题的有效方法,但是也不要忽视“分配”的“均衡”问题,不然后果可能更加严重哦!
发表评论
-
线程属性pthread_attr_t简介
2013-01-05 10:57 3938本文编辑整理自: http://hi.baidu.c ... -
避免内存碎片
2012-12-13 10:49 1499许多书籍提到过内存碎片,也看到一些方法防治内存 ... -
Linux程序设计中由线程使用不当引起的内存泄漏
2012-12-13 10:27 1409Linux程序设计中,创建线程时调用pthread_ ... -
EPOLL ET 模式下事件触发的场景
2012-09-25 10:13 1886ET模式称为边缘触发模式,顾名思义,不到边缘情况,是死都 ... -
linux惊群问题之udp
2012-09-25 10:12 1612今天测试udp服务器进程时发现log中记录了 ... -
getaddrinfo()函数详解
2012-09-19 10:59 8861. 概述IPv4中使用gethostbyname()函数完成 ... -
Linux的mmap文件内存映射机制
2012-09-19 15:00 2353在讲述文件映 ... -
Berkeley DB 由浅入深【转自架构师杨建】
2012-09-19 15:00 1976在网上看到不少介绍Berkeley DB的文章,几乎 ... -
linux 多线程编程
2012-09-19 15:00 1528进程与线程 进程是程序执行时的一个实例 ... -
pthread_cond_wait()
2012-09-25 10:13 845/************pthread_cond_w ... -
linux下创建守护进程(daemon process)代码
2012-09-18 13:47 1661#include <stdio.h> ... -
dup and dup2的剖析
2012-09-18 13:35 675dup和dup2都可用来复制一个现存的文件描述符,使两个 ... -
C语言系统资源控制(getrlimit && setrlimit)
2012-09-18 11:52 996每一个进程都有自己的一组资源限制,在(*)inux系统中 ... -
UNIX缓冲机制
2012-09-18 11:11 1013某日一朋友写了一个HELL ... -
再谈应用环境下的TIME_WAIT和CLOSE_WAIT
2012-09-13 15:15 1095昨天解决了一个HttpClient调用错误导致的服务器异 ... -
实战Nginx与PHP(FastCGI)的安装、配置与优化
2012-08-17 17:00 979一、什么是 FastCGI FastCGI是一个可伸缩 ...
相关推荐
针对古诗群文阅读的难点,如内容多、理解难度高、时间紧张以及方法习得与古诗特性相悖等问题,教师需要精心设计教学策略。 首先,"群"时顾"文",更要见"生"。在选择古诗群文阅读的文本组合时,教师应兼顾文本的关联...
比如,教师可以设计一系列问题,帮助学生思考诗中所用的象征、隐喻等修辞手法,进而理解诗人如何通过这些手法传达情感和意境。教师还可以引导学生进行小组讨论,通过交流各自的理解和感受,促进学生的批判性思维和...
### 癫痫几个临床研究问题的思考 #### 一、癫痫的基本定义与概念 癫痫是一种常见的神经系统疾病,其特征在于大脑神经元异常放电导致的一系列症状。在现代医学领域,对于癫痫的定义有着多种表述方式: 1. **电生理...
" 在IT工作中,独立思考和解决问题的能力很重要,不能过度依赖他人。 5. **自我提升** - "如果你觉得现在走的辛苦,那就证明你在走--上坡路"。在技术领域,持续学习和不断提升自己的技能是必要的。 6. **抗压能力*...
- 描述蚊子成群的场景:夏蚊成雷,私拟作群鹤舞于空中,心之所向,素鹤舞于空中,果然鹤也;昂首观之,项为之强。又留蚊于素帐中,徐喷以烟,使之冲烟而飞鸣,作青云白鹤观,果如鹤唳云端,为之怡然称快。 2. 孔子...
他在这首词中融入了自己对逆境与个体生存态度的深刻思考,展现了在困境中寻找自我价值的心路历程,也成为了他个人思想转变的一个见证。通过这首词,我们不仅能够感受到苏轼在黄州时期的孤独与寂寞,更能体会到他在...
词的上片以“三径初成,鹤怨猿惊,稼轩未来”暗示诗人渴望归隐的心境,而“云山自许,平生意气”则流露出他对自然和田园生活的向往。然而,“衣冠人笑,抵死尘埃”反映了他被世俗眼光束缚,无法摆脱官场纷扰的无奈。...
2. 张岱的诗句《则隐隐露白,如驱千百群小鹅,擘翼惊飞我的心中已没有瀑布了。我的心随潭水的绿而摇荡》的主要内容是什么?(答案:诗句描绘了作者对自然景色的描绘和对生命的思考) 3. 专题活动的目的是什么?...
”提醒我们学习与思考并重,避免盲目读书。 6. 向他人学习的《论语》名句有“三人行,必有我师焉。择其善者而从之,其不善者而改之。”以及“见贤思齐焉,见不贤而内自省也。”这两句话都强调了向周围的人学习优秀...
16. **远、色、近、听、无、声、春、还、人、来、惊**:空间、视觉和听觉的描述,培养孩子的感官体验和季节感知。 17. **对、说、是、叶、圆、夏、秋、雪、肚、就、冬**:语言表达和四季变化,增强孩子的表达能力和...