我们经常会碰到由于不知道如何配制应用服务器线程而导致应用服务器过载或崩溃的问题。尽管此类问题经常出现在PHP语言中,但是在其它语言中也会出现这些问题,它们所表现出来的都是同一类问题。

这些问题通常与队列理论及低负载下动态多层队列行为有关,也与吞吐量及到达率和服务时间有关。这样要进行合理的系统配置就变得更为困难,再加上默认设置比较差,而且繁忙系统也缺乏直觉。最后,多核CPU结构很难理解而且实时排除故障也很困难。

但是,若您仔细阅读下文解释,您会发现解决这一问题也很简单。

首先,需要理解问题产生的原因,应用服务器在高负载时要么是CPU不够,要么是RAM不够或者两者都不够,虽然RAM问题通常就是CPU问题。不管是RAM不够还是CPU不够,都是灾难性的,因为它们会导致服务器崩溃,而配置较差的服务器情况会更糟。

导致该问题产生有两个重要的因素。

第一个因素是:很多应用程序编写得并不好,而且在CPU上运行的很慢,通常要等1或数秒才开始执行。但是这种慢性执行速度通常在快速测试及开发服务器或有强大硬件的上线系统上表现的并不明显。但是,当系统在低载时,计算能力低下的情况下,若发生这种状况,确实是一种灾难。

第二个因素是:许多应用程序很消耗RAM,这主要是因为无用的大型的DB结果缓存,或内存泄漏,导致占用了很大的内存。每天我们都会发现机器中运行的一些程序平均每个实例占用内存达100-256MB, 最差的单个进程甚至可能使用500MB以上的内存。

以上例数据作参考,若一个16核的机器运行32个程序,仅仅应用程序,将至少占用32x256MB或8GB RAM。甚至配置最好的服务器,也会出现这样的问题。由于程序占用空间大,若RAM为4-8GB,情况会更糟。

若系统负载较大且延迟时间长的话,进程数目会增加。这是因为当Apache中的应用程序调度器等若发现所有进程都很忙的话,他将创建更多的进程,直到达到MaxClients(或FPM子进程数量)中设置 的极限值。通常有256子进程,乘以256MB, 将达到64GBRAM, 远远超过应用服务器的RAM。

这一问题的直接后果就是,系统在进程数较少的时候,就开始交换,这将导致进程延迟及进程数量增加。 这种死循环的通常特点是:CPU过载,进程数量多,低RAM,swap使用过多,最终导致网站崩溃。 最坏的后果就是,由于swap使用过多,你甚至不能够SSH登陆进系统去解决问题。

另一个导致系统失败的原因就是,当有足够的RAM的时候,CPU却严重过载,然而系统却在数百个Apache进程中频繁交换。这将扼杀所有吞吐量,更别提你想登陆进去。

最后,我们发现数据库性能严重影响系统整体性能。不管应用服务器是否繁忙,数据库回应速度慢会使进程数量增多,导致服务器RAM不足。

解决问题的方法很直截了当,就是将进程数量最大值设置为2倍核数量。同时,要确保在达到最大内存使用量时,你有足够的RAM可以处理进程。这种情况下,CPU负载很大时,系统会变慢,但是,在这种配置下,会以合理的加载量,一直排在队列中处理进程。

我们将其设为2倍核数,是因为进程有延迟。例如,如果你要连接远程DB,进程将在此链接过程中,处于暂停状态,所以,在这段时间,你必须有额外的程序可以使CPU利用达到最大。

但是有个例外,就是当你有服务器之外的RPC请求时,如查询系统中的Lucense或Solr, 或真实的远程系统如Facebook。 这些情况不在本博客讨论范围内,但是它们采用了更复杂的配置及监控以确保系统高载时仍能够成功运行。

总结一下,将应用服务器进程设置为2xCores,并确保有足够的RAM。这将使你的系统运行不会过载,且优化了你的系统,降低了CPU及RAM使用量,你可以在同样的硬件上进行扩展。否则,你肯定会遇到系统扩展瓶颈。