这是“成为Java GC专家系列文章”的第四篇。html
在第一篇文章 成为JavaGC专家Part I — 深刻浅出Java垃圾回收机制 中咱们学习了不一样GC算法的执行过程,GC如何工做,新生代及老年代的基本概念,在JDK7中你应该了解的5种GC类型以及他们的性能如何。java
在第二篇文章 成为JavaGC专家Part II — 如何监控Java垃圾回收机制 中咱们学到了JVM究竟是如何执行垃圾回收,咱们如何监控GC,以及那些工具可使得监控过程更高效。算法
在第三篇文章 成为Java GC专家系列Part III–如何优化Java垃圾回收机制中咱们经过实际的例子学到了一些能够优化GC的参数。同时咱们讲解了如何减小对象被转移到老年代空间,如何缩短Full GC时间,以及如何设置GC类型及内存空间。apache
在第四篇文章中,咱们将阐述Apache中MaxClients
参数的重要性,以及他如何在GC发生时,显著地影响整个系统的性能。我将提供几个例子以方便你理解MaxClients
致使的问题。同时我还会说明如何根据系统的内存状况,设置最佳的MaxClients
参数值。tomcat
NHN (译者注:NHN是做者工做的公司)服务的执行环境中存在一组Throttle valve-type参数(译者注:节流阀参数,用于控制系统负载)。这些参数对于系统来讲十分重要。下面咱们看一下Apache的 MaxClients
参数在Full GC 发生时是如何影响系统的。服务器
大部分开发人员都知道在因为GC发生而致使的”中止世界现象(STW) “(详细请参见Understanding Java Garbage Collection)。尤为是,NHN的Java开发人员常常会遇到因为GC缘由致使的Tomcat报错。因为Java 虚拟机 (JVM)管理着内存,以Java为基础的程序没法摆脱GC致使的STW现象。假如在某一个时间,当你正在操做你开发的应用时,GC开始执行。即便TTS错误没有发生,你的服务也会给客户展示未预期的503错误。架构
因为架构自己的特色,相比较而言纵向扩展,Web服务更适合横向扩展(译者注:增长服务器的数量,而不是提升件配置)。所以,整体来说,物理设备会 根据性能要求被配置成1台Apache+n台Tomcat。可是本文假设咱们的环境是1台Apache+一台Tomcat同时安装在一台主机行,以下图所 示。并发
图1:本文假射的服务执行环境jvm
仅供参考,本文描述的参数基于Apache 2.2.21 (prefork MPM),Tomcat 6.0.35,CentOS 4.72 (32-bit),jdk 1.6.0_24。工具
系统可用内存2GB,垃圾收集器使用ParallelOldGC,AdaptiveSizePolicy采用默认的设置true,堆内存空间600M
让咱们假设访问Apache的请求为 200 req/s且有10个httpd进程在运行,另外咱们暂时不考虑每一个请求的响应时间。在这种前提下,咱们假设因为full GC致使的暂停时间为1秒。当Full GC发生的时候Tomcat会怎样?
第一件进入你脑海的事情应该是Tomcat会由于full GC而中止响应任何请求。在这种状况下,当Tomcat暂停相应请求时Apache会发生什么?
当Tomcat暂停时,请求会以200 req/s的速度不断的涌入Apache。通常来讲,在Full GC发生以前,请求的响应能够快速地被10个或更多的httpd进程处理掉。可是,由于Tomcat暂停了,httpd进程会被不停地建立以相应新进请求。直到超过httpd.conf 文件中定义 MaxClients
为止。因为默认值为256,Apache不会在意请求以200 req/s的速度涌入。
这时,新建立的httpd线程将如何呢?
Httpd进程经过mod_jk 模块所管理的空闲的AJP链接,将请求转发给Tomcat。若是没有空闲链接,他会申请建立新的链接。可是,由于Tomcat暂停了,建立新链接的请求会被拒绝。所以这些请求会被存储在backlog队列中,数量的多少取决于server.xml中关于AJP Connector的设置。一旦请求数量超过backlog队列的空间限制。Apache就会返回拒绝链接错误。而且返回HTTP 503 错误给用户。
在这种假设条件下,默认的backlog队列空间是100,而请求到达速度是200 req/s。所以,full GC致使的一秒钟的暂停会使得超过100个请求返回503错误。
这样,当Full GC结束后,backlog队列中存储的内容会被Tomcat接受并在经过工做线程处理,线程的最大数量取决于MaxThreads
的值(默认200)。
在这种状况下,设定哪一个参数能够避免返回给用户503错误呢?
首先,咱们应该知道backlog的值要够大,以致于可以容纳全部由于Full GC致使暂停期间涌入的请求。换句话说太应该不小于200。
那么,这么设置以后会不会产生新的问题呢?
让咱们假设将backlog设置为200后再重复一下上面的过程。获得的结果比以前更加严重。系统内存使用量通常状况下为50%,可是,在发生 Full GC时快速增长到100%,同时致使交换内存空间快速增长,更为严重的是致使Full GC的暂停时间从1秒变成了4秒甚至更多,系统在此期间彻底宕机,不能响应任何请求。
在第一种状况下,只有100或更多的请求返回503错误。可是,当咱们把backlog调整到200后,超过500个请求会挂起3秒甚至更多地时间没法获得应答
上面这个例子能够很好的说明当你没有彻底理解各个设置之间的内在关系时(例如,对于系统的影响),盲目修改系统会致使什么后果。
那么,为何会产生这个现象呢?
问题的根源在于 MaxClients
参数的特性。
将MaxClients
设置为一个很大的值自己没有问题,但最重要的是在设定MaxClients
参数时,你要确保即便等同于MaxClients
数量的httpd进程被同时建立,内存使用量也不会超过80%。
系统的内存交换参数通常被设定为60(默认)。所以,当内存使用量超过80%时,就会进行内存交换。
让咱们再来看一下为何这个特性会致使上面那个严重的问题。当请求以200 req/s的速度涌向Tomcat时,Tomcat因为full GC暂停了。此时backlog被设置为200。Apache大约建立100个httpd进程。在这种状况下,一旦内存使用量超过80%,操做系统会激活 交换内存区域,而且因为系统认为JVM的老年代中的对象在很长一段时间内未被使用,而将他们移动到交换区域。
最终的结果是,GC使用了内存交换空间,暂停时间剧增。所以httpd进程数进一步增长。从而致使上面描述的内存使用量达到100%的状况。
这两个场合的惟一区别就是backlog的值:100 vs.200。为何只在200的状况下发生?
二者不一样的缘由在于建立的httpd进程的数量。当backlog设置为100时而且Full GC发生时,会建立100个请求的链接并保存在backlog队列中。其余请求获得拒绝链接错误信息并发挥503错误。所以,总的httpd 进程数量仅仅会略高于100。而当backlog被设置为200时,200个请求会建立链接,所以。总的httpd进程数会多于200。这样超过阀值,从 而致使内存交换的发生。紧接着,不考虑内存使用量而的设定 MaxClients
参数,Full GC致使httpd进程数量暴增,引起内存交换,下降系统性能。
若是系统的内存使2GB,MaxClients
的值在任何状况下都不该该超过内存的80%(1.6GB),以免因为内存交换致使的性能降低。换句话说。1.6GB的内存应该共享和分配给Apache,Tomcat以及那些默认被安装的代理程序。
让咱们假设代理程序被默认安装在系统,并占用了200m内存,对于Tomcat堆内存的-Xmx
被设定为 600m。所以根据top命令的结果,Tomcat会一直占用725m(Perm Gen + Native Heap Area)。最终Apache可使用700m内存空间。以下所示。
图2:测试系统的top截屏
如上所述,咱们将内存设为700m后MaxClients
应该是多少呢?
这要取决于加载模块的数量,对于NHN Web服务来讲。Apache只是个简单的代理转发,每一个httpd线程4m内存(根据top命令的结果)足以(参见图2)。所以。700m内存对应的 MaxClients
应该是175。
一个健壮的服务配置至少应该可以下降在服务过载时宕机的时间,在合理的范围内成功的应答请求。针对基于Java的Web服务。你必须检查你的服务在Full GC致使的STW时间内可否稳定的响应请求。
为了响应更多的用户请求和应对DDoS攻击,在没有全面考虑系统内存等因素的状况下,贸然地将 MaxClients
设置为一个很大的值,那么它将失去做为阀值的功能,而致使系统出现更严重的问题。
本文提到的状况只会持续3-5秒,所以绝大多数传统的监控工具都没法及时的发现。
做者 Dongsoon Choi 高级工程师@Game Service Technical Support Team, NHN Corporation.
译文地址: http://www.importnew.com/3151.html
本文转自:http://www.importnew.com/3151.html