日期:2014-5-16 浏览次数:20126次

成为JavaGC专家Part IV:Apache的MaxClients参数详解及其在Tomcat执行FullGC时的影响

成为JavaGC专家Part IV:Apache的MaxClients参数详解及其在Tomcat执行FullGC时的影响

?

这是“成为Java GC专家系列文章”的第四篇。

??????? 在第一篇文章?成为JavaGC专家Part I — 深入浅出Java垃圾回收机制?中我们学习了不同GC算法的执行过程,GC如何工作,新生代及老年代的基本概念,在JDK7中你应该了解的5种GC类型以及他们的性能如何。

??????? 在第二篇文章?成为JavaGC专家Part II — 如何监控Java垃圾回收机制?中我们学到了JVM到底是如何执行垃圾回收,我们如何监控GC,以及那些工具可以使得监控过程更高效。

??????? 在第三篇文章?成为Java GC专家系列Part III–如何优化Java垃圾回收机制中我们通过实际的例子学到了一些可以优化GC的参数。同时我们讲解了如何减少对象被转移到老年代空间,如何缩短Full GC时间,以及如何设置GC类型及内存空间。

??????? 在第四篇文章中,我们将阐述Apache中MaxClients?参数的重要性,以及他如何在GC发生时,显著地影响整个系统的性能。我将提供几个例子以方便你理解MaxClients?导致的问题。同时我还会说明如何根据系统的内存情况,设置最佳的MaxClients参数值。

?

MaxClients对于系统的影响

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:本文假射的服务执行环境

仅供参考,本文描述的参数基于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

?

STW 和HTTP 503

??????? 让我们假设访问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)。

?

MaxClients 与backlog

??????? 在这种情况下,设定哪个参数可以避免返回给用户503错误呢?

??????? 首先,我们应该知道backlog的值要够大,以至于能够容纳所有因为Full GC导致暂停期间涌入的请求。换句话说太应该不小于200。

??????? 那么,这么设置之后会不会产生新的问题呢?

??????? 让我们假设将backlog设置为200后再重复一下上面的过程。得到的结果比之前更加严重。系统内存使用量一般情况下为50%,但是,在发生 Full GC时快速增加到100%,同时导致交换内存空间快速增加,更为严重的是导致Full GC的暂停时间从1秒变成了4秒甚至更多,系统在此期间完全宕机,不能响应任何请求。

??????? 在第一种情况下,只有100或更多的请求返回503错误。但是,当我们把backlog调整到200后,超过500个请求会挂起3秒甚至更多地时间无法得到应答

??????? 上面这个例子可以很好的说明当你没有完全理解各个设置之间的内在关系时(例如,对于系统的影响),盲目修改系统会导致什么后果。

??????? 那么,为什么会产生这个现象呢?

??????? 问题的根源在于?MaxClients?参数的特性。

???????