“在一些高大上的科幻小说或者科幻片中,如果没有出现“熵”,那么肯定就不是硬科幻”,这是多年前一个比较喜欢装的哥们在聊起硬科幻时候的一个结论。虽然搞了几十年IT,不过对于信息熵还是一知半解。似乎这个硬科幻的词汇应该永远和我无缘。不过这几天确实被“熵”给深深的伤到了。我们的一套D-SMART系统接了几十个运维对象,自从因为网络安全要求启用HTTPS后,在一个客户那边经常出现一些卡顿,有时候系统就特别慢用户觉得无法忍受。开始的时候用户系统是跑在一台虚拟机上,大家怀疑是虚拟机性能不行,就迁移到了一台物理机上。这台物理机和以前的虚拟机所属的物理机的配置和型号是一模一样的,不过现在是独享这台服务器了。不过迁移之后并没有解决以前的问题,卡顿依然存在。于是用户希望我们能够定位一下问题。通过把这台服务器纳入到D-SMART进行监控后,我们发现这种卡顿是周期性出现的,卡顿最严重的时间和我们的定时数据采集任务重合度较高。D-SMART的任务平台实际上已经能够自动分批次调度大批量作业,三个分布式任务节点同时还会对同时并发启动的任务进行批次启动。按理说也不应该出现负载过高的情况。根据D-SMART的采集信息看,出现卡顿的时候,CPU使用率确实比平时要高,大概能够达到60%-80(不卡顿的时候大约在10%以下),其中SYS CPU达到20-30%。从CPU的指标上看,确实存在异常,不过好像并没有达到CPU使用率的瓶颈。而且SYS CPU特别高,这个可能存在系统核心调用方面的问题。D-SMART并不具备深度分析LINUX KERNEL的能力。于是我们借助一些LINUX内核监控的工具对一些内核资源进行监控。发现了一些蛛丝马迹:
操作系统的熵池经常会出现耗尽的现象。而且熵池耗尽的时间点和系统卡顿的时间点重合度很高。为什么熵池耗尽会出现卡顿呢?要想搞清楚这个问题还是有点复杂的。经过一顿苦读,老白终于弄明白了信息熵是咋回事了,并且也弄明白了这个系统卡顿的可能原因是什么了。熵原本是一种无序,熵值越高,无序性越强。我们这个宇宙总是有向无序变化的趋势的,这就是宇宙无序性定理。是不是很高大上,不过有点跑题了。实际上我们的计算机系统是一种有序的系统,如果在计算机系统中要产生真正的随机数仅仅依靠有序的cpu时钟是不可能实现的。必须要引入一些无序的因素,比如磁盘的运转,风扇的转动,键盘的输入,鼠标的移动等等。LINUX的驱动程序会将这些“熵”采集起来,放入熵池。另外,熵池也需要输出熵来协助系统生成随机数。随机数对于很多系统来说十分重要,比如加密算法等。HTTPS访问需要随机数、SSH连接需要随机数,加密解密需要随机数。甚至我们的任务调度平台的调度算法都大量的使用随机数。于是乎,这套系统的熵池不够用了。为了验证这一点,我们在系统卡顿并且熵池接近于0的时候通过ssh登录这套系统,发现ssh连接变得十分缓慢,而当熵池达到1000以上的时候,ssh又变得十分流畅了。在LINUX官方的资料里,老白也看到了熵池如果低于1000,会出现CPU出现SPIN的问题。
可以看出,熵池的大小是4096,这个在OS安装后就不能改变的,而entropy_avail是当前可用的熵池字节数,如果这个数量较小,而系统的随机数申请较快,那么就可能出现熵池的收集速度慢于消费速度的情况。此时就很容易出现性能问题了。要解决这个问题,一般来说可以使用rng-tools工具,这个工具中的rngd服务可以主动的从硬件上采集熵,并放入熵池中,比起操作系统自己采集熵的速度要快很多。于是在系统上安装了一个rng-tools工具。通过rngd来看看系统中有哪些硬件的熵源可用。
居然没有任何硬件熵源?在老白刚刚看的资料里,起码INTEL的cpu里就有rdrand指令可以作为熵源。难道这台服务器的CPU不支持rdrand指令?
确实是没有,难道是十年前的CPU?
还真不含糊,这老古董2012年就停产了,怪不得没有物理熵源可用。这种情况我们就只能用haveged去加快熵的收集了。于是通过yum源安装了一个haveged。发现确实熵池有所改善了,在大多数情况下,熵池能够维持在1000以上,不过还是经常会出现只有1-200的情况。而这时候系统还是有点慢。这种情况就只能祭出终极方法了。直接从无阻塞的快速随机设备dev/urandom采集熵放置到/dev/random中,虽然很多专家并不建议采用这种做法,因为这种方法并不能真正增加熵池,并且还会降低随机数的质量,导致加密算法可靠性下降。不过这种做法可以确保entropy_avail会保持在较高的水平,从而避免CPU出现SPIN的问题。
调整的效果是立竿见影的,设置后,熵池立马就改善了。
无论如何波动,熵池的可用字节都保持在3000以上。再观察系统情况,发现卡顿现象消失了。周期性的CPU飙升也消失了。总结有耐心看到这里的朋友已经算是对熵有真爱了,这个优化案例实际上理解起来还是有点困难。首先是,怎么把问题定位到是“熵”的原因呢?这个定位是有些偶然性的,因为在启用HTTPS访问之前,本系统的卡顿现象不是特别明显(当然周期性数据采集的时候系统比较慢一点,CPU使用率比较高的问题是一直存在的,当时大家觉得可能是设备过于老旧,而且虚拟机的资源不足导致了这个问题),上了HTTPS后,卡顿就十分明显了,而且产生一个ssh连接的速度也变得十分慢。从OS层面也观察到了CPU使用率较高,于是更换了服务器。服务器更换后卡顿现象并未缓解,并且在系统没什么作业在运行的时候CPU使用率会莫名其妙的高,正是这个现象让我们想到了系统可能处于某种资源不足的状态,从而导致SPIN。于是进行内核资源分析就成为了下一步分析的重点。
从内核资源分析中,我们很快就定位到了entropy存在周期性的波动情况,于是开始分析熵,以及熵池不足可能的现象。正好这一现象和我们观察到的系统周期性卡顿现象十分一致。
另外一个问题是熵池为什么会不足呢?这个案例是由于一台老旧的服务器缺乏硬件熵源,从而在HTTPS访问、我们本身任务平台大量启用ssh链接,以及任务平台调度时大量使用随机数,HASH值,这些大量消耗熵的应用存在周期性调度的问题,于是出现了周期性的熵需求高峰,导致熵的收集速度不足,随机数函数调用等待熵池补充数据,导致CPU spin,最终引起了卡顿的现象。
实际上这种熵池不足的问题,在一些云平台环境中也经常存在。由于服务器缺乏硬件熵源,而且多个虚拟机使用同一物理服务器,而且物理服务器上没有鼠标键盘等物理熵源,正常情况下LINUX内核对熵池的补充速度有可能赶不上消耗速度。在一些大型的云运营商里,有大型物理熵源来为熵池做补充,这方面的问题在云平台层面已经做了优化,因此大型公有云一般很少会出现这种问题。一些私有云或者小型公有云运营商就不一定很好的解决了这个问题。
如果你的系统出现了类似问题,采用本文中的两个软件是可用解决大多数问题的。如果在一台CPU支持DRNG的服务器上,使用rng-tools就可以较好的解决这个问题了。rngd会协助LINUX内核快速补充熵池。
这种情况下,我们只需要启用rngd服务,你的熵池一般就不会出问题了。