我用一些服务来维护一个Gentoo服务器,包括Apache。 这是相当低端的(2GB内存和2核心的低端CPU)。 我的问题是,尽pipe我尽了最大的努力,一个过载的Apache崩溃了整个服务器。 事实上,在这一点上,我已经确信Linux是一个可怕的操作系统,不值得任何人在负载下寻求稳定性。
我试过的东西:
只是强调一下:我不在乎Apache本身是否在负载下,我只是希望我的系统的其余部分保持稳定。 当然,在短时间的密集负荷之后,阿帕奇能够很快恢复,这是一件非常棒的事情。
现在我大部分都不知道,在这个时代,人类怎么能devise一个操作系统,在这个看起来很简单的任务中(不允许一个系统组件崩溃整个系统)似乎几乎是不可能的 – 或者至less是非常的很难做到。
请不要build议像虚拟机或“购买更多内存”的东西。
在朋友的帮助下收集的更多信息:当cgroup oom杀手被调用时,进程挂起。 这是呼叫跟踪:
[<ffffffff8104b94b>]? prepare_to_wait + 0x70 / 0x7b [<ffffffff810a9c73>] mem_cgroup_handle_oom + 0xdf / 0x180 [<ffffffff810a9559>]? memcg_oom_wake_function +为0x0 / 0x6d [<ffffffff810aa041>] __mem_cgroup_try_charge + 0x32d / 0x478 [<ffffffff810aac67>] mem_cgroup_charge_common + 0x48 / 0x73 [<ffffffff81081c98>]? __lru_cache_add + 0X60 / 0X62 [<ffffffff810aadc3>] mem_cgroup_newpage_charge + 0x3b / 0x4a [<ffffffff8108ec38>] handle_mm_fault + 0x305 / 0x8cf [<ffffffff813c6276>]? 时间表+ 0x6ae / 0x6fb [<ffffffff8101f568>] do_page_fault + 0x214 / 0x22b [<ffffffff813c7e1f>] page_fault + 0x1f / 0x30
在这一点上,Apache的内存cgroup实际上是死锁,并在系统调用中的CPU(所有上面的调用跟踪)。 这似乎是在cgroup实施中的一个问题…
我讨厌这样说,但你似乎在问错误的问题。
这不是要阻止Apacheclosures你的服务器,而是让你的networking服务器每秒提供更多的查询 – 这足以让你没有问题。 重构问题的一部分答案就是限制Apache,以免在高负载下崩溃。
对于第二部分,Apache可以设置一些限制 – MaxClients是一个重要的configuration。 这限制了允许运行的孩子数量。 如果您可以从Apache上卸载长时间运行的进程(例如下载大文件),那么这是Apache能够为PHP提供服务的另一个插槽。 如果文件下载必须由PHP层进行validation,他们仍然可以这样做,然后将其传递给更加优化的静态内容的Web服务器,例如使用Nginx发送文件
同时,在每一个请求中,每一个请求都要求Apache运行PHP最慢的方式 – 作为一个CGI(无论你使用的是哪个Apache MPM) – 也让机器花费大量的时间不运行你的代码。 mod_php明显更优化。
当Apache和PHP层被适当地优化时,PHP可以做大量的stream量。 例如,2010年12月11日,我运行的这对PHP服务器在24小时内完成了近一千九百万次点击,其中大部分时间在上午七点到八点。
这里还有很多其他的问题,以及有关优化Apache和PHP的其他文章,我认为在责备Linux / Apache&PHP之前,您需要先阅读它们。
当你正在处理一个生产Apache服务器,你必须有一个平均的进程大小,特别是与PHP,我会build议你:
MaxClients调整为AVERAGE_MEMORY / RAM_DEDICATED_TO_APACHE 在RAM_DEDICATED_TO_APACHE的情况下,它必须是对TOTAL_RAM减去需要机器其余部分的RAM的另一种估计(如果你在同一台机器上运行一个数据库,那么对数据库应该是慷慨的)。
我真的推荐你使用Varnish ,你可以在保存机器的不同端口上轻松地运行2台服务器,并将静态文件路由到一个专门的文件(媒体)服务器(lighthttpd,nginx)或一个带有worker的apache实例, 。 当然也可以用清漆来清理静态内容。
拆分负载非常重要,因为如果不这样做,您将使用相同数量的ram来提供任何静态文件(该文件需要小于1MB)。
如果你真的需要确保永不消耗所有内存,你可以安装一个新的每2分钟运行一次的cronjob(考虑更less或者更多),把50调整到任意数量的最低内存,这个数字至less在30以上; 你需要一些内存来停止服务器。
vmstat -SM | tail -n 1 | awk 'BEGIN{ "date" | getline date }{if($4 + $6 < 50){ system("/etc/init.d/httpd stop"); system("/etc/init.d/httpd start"); print "Rebooting apache on " date >> "/var/log/apache-reboots.log"}}'
这是限制你内存的一种非常强硬的(肮脏的)方法,但是如果你不确定每个apache进程的平均内存是多less,并且在你的日志文件中看到多个重启(“/ var / log /apache-reboots.log“),你应该调整你的apache MaxClients , MaxRequestsPerChild , ThreadsPerChild以避免未来的硬重启,随着时间和调整,你将有你的服务器的确切configuration。
几个一般的东西,你可以尝试:
您是否尝试将/ proc / sys / vm / overcommit_memory更改为2? 这意味着kenel不会分配比swap +可用ram的可configuration百分比(proc / sys / vm / overcommit_ratio)更多的内存。
在Apache不能分配内存的情况下,Apache会失败,但是已经加载的服务,如openSSH将继续运行。
我应该补充,我从来没有尝试过,只是现在发现了这个设置。 我很乐意听到任何人知道更多。 否则,我会明天testing,因为我的问题与问题中所描述的完全相同。
我发现了这个问题
整个内存限制cgroup设置oom_adj为15竟然是非常愚蠢的。 cgroup中所有进程的调整得分均为1000,因此当cgroup耗尽内存时,系统会杀死随机进程,并且通常会出现故障。
删除设置oom_adj的行后,我没有任何系统崩溃。
这可能会有点晚,但我可以说责怪操作系统根本不是要走的路。 操作系统的devise是为了满足几种不同用例场景的期望,因此,您必须对其进行configuration以满足您的要求。
不仅如此,但是如果你有太多的负载,系统崩溃,那么你必须优化你的系统,或扩大你的networking。
而过早优化可能会使事情在以后变得痛苦,从一开始就没有任何优化可以产生相同的后果。 这完全是关于平衡。
然而,你声称你的目标是防止系统崩溃..但是然后继续说你的解决scheme没有工作。 但其中有些人确实工作,你只是不满意的结果。
当你用完内存,你交换。 或事情崩溃。 故事结尾 。 如果你不想交换,你必须:
a)限制您的传入连接。 这具有将人们带走的效果
b)将他们发送到积压。 这会导致现场减速或死亡。
c)购买更多的记忆。 你不想这样做
d)扩展您的networking。 你也不想这样做
e)负载平衡。 这很像'D'
没有仔细的优化,微调和扩展..你不能防止所有这些事情发生。
根据我的经验,我了解到,通过使用上述所有的细微组合,通常会导致最终的结果。
首先,我使用apache2 + mpm_event + mod_fcgid 。 我会仔细configuration几乎每个可能的选项apache必须configuration。 这可能需要一个晚上才能完成,另一个需要正确的。 但这将是值得的。
我会确保总是有一个工作人员准备好处理传入的连接,并让它增长,但限制在一定的合理范围内。 这可能会牺牲一些速度,但会导致稳定性。
其次,我使用CGroups and IO Priority / CPU Priotiy来为不同的优先级安排不同的服务组。
任何100%关键的东西,我总是需要访问,它们被保留了一块内存,并且设置了更高的IO和CPU优先级。 我会掀起一个剧本,每小时左右设置这些优先事项,以便孩子们将inheritance这些优先事项,如果他们的父母改变。
接下来是DNS,然后是Web,然后是Mail。 按此顺序。 这样,如果有什么行为不当,更关键的因素是有利的。
使用monitor software,检查是否在线,如果没有,重新启动它们。 如果有任何内容已经使用超过XMB的内存,对于X Cycles …并且无法连接到服务(即在http://...:80 ),请终止服务并重新启动服务。 如果在X周期内重新启动超过X次,则超时(并通知手动检查)。 你可能会偶尔下降一些用户,但至less你的系统保持稳定!
第三,如果你有一个专用的服务器,ID把所有的网站服务放在一个separate disk 。 主要通过不同的控制器保持IO操作。
第四,检查Apache模块,如mod_bw和mod_qos 。 mod_bw可以做的不仅仅是限制每个虚拟主机的带宽,mod_qos …这是一个服务质量模块,可以帮助缓解一些问题。
除了完全成熟的QoS模块所期望的function外,它还可以帮助阻止缓慢的DoS,限制NULL连接,甚至可以在服务器达到一定的并发连接阈值时closureskeepalive。
最后,我会设置一些intelligent caching front ends或load balancer 。 例如:使用一些虚拟机实例,也许使用Varnish或者NGinx,caching上游的静态文件。 这将卸载Apache为了提供静态内容而需要的所有开放时隙。
我真的不确定当你有很多stream量时你会期望发生什么。 你希望它既能保持稳定,又不想在压力下丢失任何function,而且你不想优化任何东西,而且你也不想升级或扩展你的networking?
好吧,如果你不想改变任何事情,你如何期待问题消失?