`
jarfield
  • 浏览: 202641 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Linux随机数发生器导致Apache进程全部Block的问题追查

阅读更多

今天上午,运营同事报告一个严重故障,现象是网站页面速度非常慢,基本不可用。工程师开始追查问题。

首先介绍一下系统架构:前端 Apache,中间PHP,后端MySQL,经典的LAMP架构。

 

猜测数据库出现性能问题

 

第一反应,怀疑数据库数据量太大。我们一直定期清理数据库,保证单表数据量在一定范围内。而这段时间一直没有清理,数据量可能过大。立刻执行delete语句,单表减少100W条记录。但是,问题依旧。

后来,DBA同学发现慢查询,存在filesort。果断增加索引,慢查询消失。但是,问题依旧。

无奈之下,怀疑机房网络问题。但是其他产品线都没有问题,网络组也没有故障通报。因此,否决这种可能。

 

线下环境复现故障

时间已经到了下午5点,决定重新梳理思路,反复观察故障现象。总结几点:

  • 页面响应速度不稳定,或慢或快,或稍慢,或奇慢,缺少一种规律性
  • 甚至,在一位同事的电脑上,刷新几次都很快。

由于没有权限看线上日志(其实代码中也没有打任何日志),无法从日志中获取有效信息。为了方便调试,我们决定在线下环境部署代码并尝试复现故障。

结果,线下环境中,故障基本必现。可以肯定,与网络环境没有关系,与线上的memcahced/mysql的运行状况也没有关系。

我们在PHP代码的不同位置插入调试代码 echo ‘xxx’;exit;  , 试图确定何处代码在堵塞。

我们惊奇的发现,当一个页面处于等待响应的状态时,后续页面必然也在等待。而且,后续页面没有执行任何PHP代码。我们推断,Aapache进程block住了!

 

Strace Apache进程

为了搞清楚Apache进程block在什么地方,我们使用strace工具观察Apache进程的系统调用。

先找出Apache的进程号。

 

[root@vm11030032 ~]# ps aux|grep httpd
root      3553  0.0  2.6 312672 13476 ?        Ss   Aug03   0:03 /usr/local/apache2/sbin/httpd -k restart
www       4759  0.0  4.4 320664 22584 ?        S    20:31   0:00 /usr/local/apache2/sbin/httpd -k restart
www       4760  0.0  3.2 316548 16672 ?        S    20:31   0:00 /usr/local/apache2/sbin/httpd -k restart
www       4761  0.0  3.2 316548 16672 ?        S    20:31   0:00 /usr/local/apache2/sbin/httpd -k restart
www       4762  0.0  3.2 316548 16672 ?        S    20:31   0:00 /usr/local/apache2/sbin/httpd -k restart
www       4763  0.1  4.9 319552 25036 ?        S    20:31   0:00 /usr/local/apache2/sbin/httpd -k restart
www       4766  0.0  3.2 316548 16672 ?        S    20:32   0:00 /usr/local/apache2/sbin/httpd -k restart
root      4890  0.0  0.1  61188   732 pts/3    R+   20:35   0:00 grep httpd
www      30809  0.0  6.0 327304 30772 ?        T    16:43   0:01 /usr/local/apache2/sbin/httpd -k restart
  

然后,随便挑一个进程号,strace上去:strace -p 4759

接着,反复刷新页面,总有一个请求会落到PID为4759的进程上。

终于,一个请求过来,快速刷屏,戛然而止,输出内容定格在:

 

connect(107, {sa_family=AF_INET, sin_port=htons(7634), sin_addr=inet_addr("10.73.19.246")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=107, events=POLLOUT}], 1, 1000) = 1 ([{fd=107, revents=POLLOUT}])
connect(107, {sa_family=AF_INET, sin_port=htons(7634), sin_addr=inet_addr("10.73.19.246")}, 16) = 0
write(107, "get APPS_SCREEN_API_CURR_TOKEN \r"..., 33) = 33
read(107, 0x14130e48, 8196)             = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=107, events=POLLIN}], 1, 200) = 1 ([{fd=107, revents=POLLIN}])
read(107, "VALUE APPS_SCREEN_API_CURR_TOKEN"..., 8196) = 107
write(107, "quit\r\n", 6)               = 6
read(107, 0x14130e48, 8196)             = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=107, events=POLLIN}], 1, 200) = 1 ([{fd=107, revents=POLLIN}])
read(107, "", 8196)                     = 0
shutdown(107, 2 /* send and receive */) = 0
close(107)                              = 0
open("/dev/random", O_RDONLY)           = 107
read(107,
 

注意,最后一行输出并不完整,说明Apache进程堵塞在read系统调用上。read的对象是 /dev/random,看起来与随机数有关。但是,哪里的代码会用到随机数呢?

 

找到关键代码

根据前面输出的IP和PORT,包括调用参数,我们确定这是在访问memcached。于是,顺藤摸瓜,找到访问memcached之后的一段代码:

 

$size = mcrypt_get_iv_size (MCRYPT_BLOWFISH,MCRYPT_MODE_ECB);
 
$iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
 
$m = mcrypt_ecb (MCRYPT_BLOWFISH,$key,$dmcryptText,MCRYPT_DECRYPT,$iv);
 

其中,第二行代码,出现了RANDOM,查了一下php手册,当第二个参数为MCRYPT_DEV_RANDOM时,mcrypt_create_iv存在堵塞的可能性。MCRYPT_DEV_URANDOM则不会阻塞。

 

线上故障得以解决

虽然还不知道具体原因,但是本着快速解决问题的原则,决定替换参数立刻上线。

果然,问题得以解决,刷新页面时,从未如此酣畅淋漓!

 

分析故障现象

线上的Apache进程很大的概率会走到上述代码,因此很可能被block一段时间。于是,当前页面就会很慢。

当所有Apache进程都被block时,后续请求必须等待空闲的Apache进程,因此后续页面都将变得很慢。

由于Apache进程unblock的时间不可确定,因此后续页面的等待时间也时长时短。

 

深挖原因

虽然问题解决,但是本质原因还没搞清楚:为什么MCRYPT_DEV_RANDOM会堵塞,而MCRYPT_DEV_URANDOM从不会堵塞。

google了一下/dev/random,维基百科一如既往的靠谱:

 写道
在这个实现中,发生器保存了来自熵池中噪声的数据位数的估计值,而随机数是从该熵池中创建的。
在读取时,/dev/random设备只会返回熵池中噪声数据中的随机字节。
/dev/random应当可以适用于要求非常高质量随机性的应用,例如产生公钥或一次性密码本。
若熵池空了,对/dev/random的读操作将会被阻塞,直到收集到了足够的环境噪声为止[3]。

这样的设计使得/dev/random是真正的随机数发生器,提供了最大可能的随机数据熵,建议用于产生保护高价值或长保护周期的密钥。

/dev/random的一个副本是/dev/urandom ("unlocked",非阻塞的随机数发生器[4]),它会重用内部池中的数据以产生伪随机数据。
这表示对/dev/urandom的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random的。
该设备文件是设计用于密码学安全的伪随机数发生器的,可以用于安全性较低的应用。
 

大概的意思就是,/dev/random生成随机数时,依赖熵池。如果熵池空了或不够用,对/dev/random的读取就会堵塞,直到熵池够用为止。/dev/urandom则不会堵塞。有得必有失,urandom的随机性弱于random。

 

详解熵池

熵池本质上是若干字节。/proc/sys/kernel/random/entropy_avail中存储了熵池现在的大小,/proc/sys/kernel/random/poolsize是熵池的最大容量,单位都是bit。如果entropy_avail的值小于要产生的随机数bit数,那么/dev/random就会堵塞。

那么,为什么熵池不够用呢?

google了一下资料,熵池实际上是从各种noice source中获取数据,noice source可能是 键盘事件、鼠标事件、设备时钟中等。linux内核从2.4升级到2.6时,处于安全性的考虑,废弃了一些source。source减少了,熵池补给的速度当然也变慢,进而不够用。

其实,通过消耗熵池,可以构造DOS攻击。原理很简单,熵池空了,依赖随机数的业务(SSL,加密等)就不能正常进行。

 

补充熵池

Linux服务器在运行时,既没有键盘事件,也没有鼠标事件,如何快速积累熵池呢?

google了一下资料,发现有一些程序可以自动补充熵池,例如rngdrng-tools

我在Linode VPS上尝试了一下rngd,效果非常明显。

先观察rngd启动前的熵池大小: watch cat /proc/sys/kernel/random/entropy_avail ,在100~200之间。

然后启动rngd:sudo rngd -r /dev/urandom -o /dev/random -f -t 1

熵池立刻飙升到3712,接近4096的上限。

 

总结

先吐槽:没有日志的系统太扯淡了,追查问题只能靠推测或猜测,耽误大量时间。

后总结:如果业务依赖随机数,那么最好使用工具主动补充熵池。

再吐槽:熵池一直够用,今天才出现不够用的情况。究竟是神马原因,还搞不清楚。码农真苦!

31
2
分享到:
评论
16 楼 wangzhewang 2013-02-23  
牛!,希望更多分享!
15 楼 JeffreyZhao 2013-02-23  
meifangzi 写道
只不过是打个工,帮人解决问题
要这么自豪么.....

这位兄弟只不过是灌个水,放松放松心情
要表现的这么二么……
14 楼 mfkvfn 2012-12-05  
虽然不用php,不过看着好像很牛的样子,顶1下。
13 楼 Syngain 2012-12-05  
12 楼 yanweimin7 2012-12-04  
meifangzi 写道
只不过是打个工,帮人解决问题
要这么自豪么.....

嫉妒么,从楼主的文字中,可以看出还是很牛的。。
11 楼 zhengdl126 2012-12-04  
居然log都没,狂刷页面到strace,有想法~
10 楼 337240552 2012-12-04  
9 楼 meifangzi 2012-12-04  
只不过是打个工,帮人解决问题
要这么自豪么.....
8 楼 rmn190 2012-12-04  
很有现场感
7 楼 jarfield 2012-12-04  
fyland 写道
24 Sep 12 Mcrypt响应慢的一个原因
作者: Laruence
本文地址: http://www.laruence.com/2012/09/24/2810.html
===================================================

这篇文章应该跟你的问题差不多,可以参考一下


恩,不过我的文章最早是8月份学的,比鸟哥先发,很荣幸。
6 楼 bei79 2012-12-03  
学习了。支持。
5 楼 fyland 2012-12-03  
24 Sep 12 Mcrypt响应慢的一个原因
作者: Laruence
本文地址: http://www.laruence.com/2012/09/24/2810.html
===================================================

这篇文章应该跟你的问题差不多,可以参考一下
4 楼 zhangzijun1984 2012-12-03  
赞,谢谢分享啦!
3 楼 feikiss 2012-12-03  
好文章!专研精神值得学习!
2 楼 crazywen2011 2012-12-03  
堪称一悍农……
1 楼 mmhotsky 2012-12-03  
学习了!

相关推荐

    计算统计学课程作业30种随机数发生器(组合随机数发生器)matlab代码

    本课程作业聚焦于30种不同的随机数发生器,其中包括5种基础的随机数发生器及其两两组合形成的25种组合随机数发生器。所有这些实现均采用MATLAB编程语言,这是一款广泛应用于科学计算的软件。 首先,我们来探讨...

    Linux随机数生成器的原理及缺陷.pdf

    Linux随机数生成器的原理及缺陷 Linux随机数生成器是所有类Linux操作系统内核的重要组成部分,它的输入来自于操作系统中随机事件的熵值,输出几乎涵盖系统中的每一个安全协议,例如生成TLS/SSL的密钥、TCP的序列号...

    main_随机数发生器_volumee3k_随机数_

    这里我们关注的是一个C语言实现的随机数发生器,标题为"main_随机数发生器_volumee3k_随机数_",其中提到了几种不同的随机数生成算法,包括平方取中法、积取中法、常数乘子法以及斐波那契随机数发生器。这些方法各有...

    基于FPGA的真随机数发生器设计与实现

    《基于FPGA的真随机数发生器设计与实现》 真随机数发生器(TRNG)在现代科技中扮演着至关重要的角色,特别是在密码学、安全通信和统计模拟等领域。文章详细介绍了如何利用FPGA(Field-Programmable Gate Array,...

    理想随机数发生器

    一个理想随机数发生器R,给定参数正整数x,它可以均匀随机产生一个闭区间[0,x]之间的实数(注意是实数,每个实数出现的概率相同)R(x)。现在给定3个正整数a,b,c,我们使用a,b产生两个随机实数R(a), R(b),问R(a) + R...

    Linux内核随机数产生器的设计与实现.pdf

    Linux内核随机数产生器的设计与实现 Linux内核随机数产生器的设计与实现是指Linux操作系统中的一种随机数生成技术,该技术通过收集系统环境中的噪声来生成高强度的随机数。这种技术在科学研究的许多领域具有重要...

    monte carlo随机数发生器

    总的来说,蒙特卡洛随机数发生器在MATLAB中的应用是通过`rand`和`randn`函数实现的,尤其在处理正态分布的问题时,`randn`功能强大且易于使用。结合蒙特卡洛方法的理论,我们可以有效地解决各种复杂的数值计算问题。

    并行随机数发生器trng源代码

    并行随机数发生器(Parallel Random Number Generator, PRNG)在现代计算机科学,尤其是高性能计算和模拟领域中扮演着至关重要的角色。TRNG(True Random Number Generator)是一种真正的随机数生成器,它从物理现象...

    真随机数发生器1.0

    一个比较好的真随机数发生器,大家都来下载啊,谢谢大家

    五种随机数发生器-C++与MATLAB代码(1)_随机发生器_

    本资源提供了五种不同的随机数发生器的实现,分别用C++和MATLAB这两种语言编写。以下是对这些随机数发生器及其相关知识点的详细说明: 1. **平方取中法(Midpoint Square Method)** 平方取中法是一种简单但不太...

    小数开方随机数发生器

    小数开方随机数发生器,信息隐藏技术实验教程

    计算统计学课程作业30种随机数发生器(组合随机数发生器)matlab代码.zip

    5. **实际应用**:学习和掌握这些随机数发生器的实现不仅有助于理解统计概念,而且在实际问题解决中非常有用,如在模拟金融市场、天气模型、疾病传播模型等领域。 6. **文件列表**:由于没有提供具体的文件名列表,...

    C51程序和PROTEUS图(随机数发生器)

    本主题主要关注如何在C51语言中实现随机数发生器,并在PROTEUS环境下进行验证。 C51程序设计: C51是针对8051系列微控制器的ANSI C编译器,它的语法与标准C略有不同,主要是为了适应硬件特性。在C51中创建随机数...

    随机数发生器原理ppt

    ### 随机数发生器原理 在信息技术领域中,随机数发生器是至关重要的组成部分之一,被广泛应用于密码学、模拟仿真等多个方面。根据其生成机制的不同,随机数发生器可以分为真随机数发生器(TRNG)与伪随机数发生器...

    上海量子随机数发生器.pdf

    上海量子随机数发生器芯片相关合作设计方案 上海量子随机数发生器芯片是基于量子原理的随机数发生器,能够生成高质量的随机数序列。该芯片的设计方案主要涉及到激光器、分束器、相位调节模块、探测器芯片等组成部分...

    高速的真随机数发生器

    【高速的真随机数发生器】是一个专门设计用于快速生成随机数的软件工具,其核心特点在于能够以超过200M字节/秒的速度产生随机数据,这在许多需要大量随机数的计算任务中显得尤为关键。在信息技术领域,随机数的生成...

    简单易懂随机数发生器

    本项目提供了一个简单的随机数发生器,旨在帮助初学者理解和应用随机数生成技术。下面将详细介绍其中涉及的知识点。 1. **随机数生成算法**: - **线性同余法(Linear Congruential Generator, LCG)**: 这是一种...

Global site tag (gtag.js) - Google Analytics