本文将介绍Apache的MaxClients参数的重要性以及在GC发生时对系统整体性能的显著影响。通过几个例子,你将会更清晰的理解MaxClients值所引发的问题。最后会介绍如何依据系统的可用内存来为MaxClients设置合理的数值。

  MaxClients对系统的影响

  NHN的服务运行环境中有大量的流控(Throttlevalve)选项,这些选项对系统的稳定运行具有重要作用。我们来看下Apache的MaxClients选项在Tomcat发生Full GC时会对系统带来哪些影响。

  大部分的开发人员都知道GC 发生中会伴随着”stop the world(STW)现象”(具体详情参考理解Java垃圾回收)。尤其是NHN的Java开发人员可能都经历过在Tomcat中由GC相关问题而导致的系统崩溃。因为JVM管理内存,因此Java应用系统不可避免的会遇到GC引起的STW现象。

  在你开发的线上系统中,GC每天都会发生很多次。在GC发生时,即便TTS没有发生,却依然可能会给用户503的错误响应。

  系统运行环境

  根据结构特点,Web服务更适合于做横向扩展而非单纯的提高单一机器的性能。所以通常根据性能需要,Web服务的服务器部署结构由一台Apache服务器和多台Tomcat服务器组成。在本文中,假设一个Apache服务和Tomcat服务部署在同一台物理主机上,如下图所示:

  

  图1: 本文假设的服务运行环境

  作为参考,本文所述参数均是基于Apache 2.2.21(prefork MPM),Tomcat 6.0.35,jdk 1.6.0_24,并运行在CentOS 4.7.2(32位)操作系统上。

  系统内存2GB,并使用ParallelOldGC垃圾回收,默认开启了AdaptiveSizePolicy选项并设置堆大小为600MB。

  STW 和 HTTP 503

  假设Apache的流量为200QPS,并开启10个httpd处理进程(尽管实际场景依赖于请求的响应时间)。在这种前提下,假设full GC导致的停顿耗时1秒,如果Tomcat发生了Full GC将会怎么样?

  首先你能想到的是full GC导致Tomcat停顿,处理中的请求将得不到响应。如果这样,Tomcat暂停,请求得不到处理,Apache将会怎么样?

  即使Tomcat因Full GC而暂停处理,而请求却仍以200 req/s的速度到达Apache。在full GC发生前,只需要10个或者稍微多一点的httpd进程就可以快速响应服务请求。但是现在Tomcat暂停了,为了处理新的请求Apache将持续创建新的httpd进程直到httpd.conf文件中定义的MaxClients阀值。因为MaxClients默认值为256,所以200 req/s的请求并不会带来太大问题。

  这个时候,新创建的httpd 进程会怎么样?

  Httpd 进程使用mod_jk模块管理的AJP连接池中的空闲连接把请求发送到Tomcat。如果没有空闲连接,则会要求创建新的连接。然而因为Tomcat处理暂停状态,新建连接的请求将被拒绝。所以这些请求将会放到堆积队列(backlog queue),队列的长度是server.xml的AJP Connector中设置的。

  如果请求数据超出了堆积队列的长度,Apache将会收到连接拒绝错误,并把这个错误以HTTP 503的方式返回给用户。

  在本例的中,堆积队列的长度默认设置为100,而请求速度为200 req/s,因此在由full GC导致Tomcat暂停的这1秒中,将有超过100的请求将会收到503错误。

  Full GC结束之后,堆积队列中的socket连接会被Tomcat接收并分配给工作线程(最大工作线程数由MaxThreads决定,默认值为200)来处理请求。

  MaxClients和堆积队列

  在上面的场景中,如何设置才能避免给用户返回503错误?

  首先我们需要知道,应该设置足够的堆积队列长度以容纳在Tomcat Full GC导致的暂停期间流入的请求。因此堆积队列最小长度至少为200(上文中QPS为200)。

  这样配置以后,是否还有其他问题?

  把堆积队列长度设置为200后,我们再次重复上面的场景。结果问题却比之前更加严重。

  正常情况下系统内存使用量维持在50%,而在发生Full GC时内存使用却迅速上升到100%,引起内存交换区(swap)使用量的极剧增加。更为严重的是Full GC导致的响应停顿由原来的1秒增加到了4秒,直接后果就是期间系统像挂掉了一样,不能响应任何请求。

  在之前的场景中,只有100左右的请求会收到 503 的错误,而增加堆积队列到200后却导致了500甚至更多的请求被挂起至少3秒不能收到任何响应。

  这个例子很好的证明了如果不能准备的理清配置信息之间的因果关系,可能会对系统带来极为严重的影响。

  为什么会这样?

  原理就是要清楚MaxClients选项的特性。

  MaxClients的值不易设置过大,设置MaxClients的关键在于即便创建了MaxClients数量的httpd进程,也要需要维持应用系统的内存使用量不应超过80%。

  系统交换区默认值为60,因此如果内存使用超过80%,系统将会发生频繁的内存交换。

  我们再来看下为什么这个特性会导致上面所述的严重后果。

  当请求的QPS为200时,Tomcat会被Full GC暂停响应,然后把堆积列队容量设置为200。起初大约有100个额外的httpd 进程会被Apache创建,紧接着内存使用量超过了80%,引起操作系统主动的使用交换区的内存空间,而因GC存活在JVM老年代中的对象被操作系统误认为长时间未使用,从而导致这些对象被移动到交换区。

  最后,当GC过程中涉及到交换区时,耗时就会迅速增加。而后httpd进程数继续增加,导致内存使用量达到了100%,从而出现了上述的严重后果。

  上述案例的前后区别仅在于堆积队列的长度:100和200。但为什么在200时会出现更严重的状况?

  原因是堆积队列不同的长度导致了httpd进程数的不同。当值为100时,在发生Full GC时100个请求所要求创建的连接被置于堆积队列中。再有新的请求会被拒绝并返回503错误,所以系统的整个httpd的进程数仅超出100很少的数量。

  但当队列长度设置为200时,有200个请求被接收并置于队列中。从而导致httpd进程的数量超过200,并触发了操作系统进行内存交换的阀值。

  所以,如果不顾内存使用情况而一味的加大MaxClients的数值,将会导致Full GC时httpd进程数迅速增加,引进内存交换并最终降低系统的整体性能。

  所以如何设置MaxClients,如何找到当前系统的阀值?

  MaxClients 取值的计算方式

  如果系统总内存为2GB,设置MaxClient的值需要保证在任何时候内存的使用量不超过80%即1.6GB,从而避免因内存交换导致的性能下降。也就是说仅有1.6GB空间供Apache, Tomcat和其他默认安装的代理程序共享和分配内存。

  假如默认安装的代理程序占用200M内存;Tomcat的堆空间设置-Xmx为600M,如下图所示,Tomcat总占用量将725M (持久代 + 本地堆空间)。Apache可使用的空间为剩下的700M。

  

  图 2:Top命令的截图

  对于Apache的700M内存,该如何设置合理的MaxClients值?

  当然这也取决于Apache加载的模块类型和数量。以NHN的Web服务为例,把Apache当作简单的代理使用,根据上图RES显示,4M空间对于每个httpd进程来说已足够使用。因此700M空间能设置的MaxClients为175。

  总结

  可靠的服务配置要能够在满载的情况下降低系统停顿时间并能够最大范围的保证成功响应用户请求。对于Java应用来说,必须要确认在Full GC引起的SWT情况下,系统的配置是否能够提供足够可靠的服务。

  如果为了应对单纯的请求增加和防止DDos攻击,在不考虑内存使用的情况下把MaxClients设置过大,那么MaxClients不但会失去作为流控的用途,反而会带来更为严重的后果。

  在这个案例中,解决问题的最优途径是加大系统的内存,或者设置MaxClients为175(上面的计算结果)以保证只有QPS超过175时才会出现503错误。

Apache的MaxClients设置的更多相关文章

  1. Java GC专家系列4:Apache的MaxClients设置及其对Tomcat Full GC的影响

    本文是GC专家系列中的第四篇.在第一篇理解Java垃圾回收中我们学习了几种不同的GC算法的处理过程,GC的工作方式,新生代与老年代的区别.所以,你应该已经了解了JDK 7中的5种GC类型,以及每种GC ...

  2. 成为Java GC专家(4)—Apache的MaxClients参数详解及其在Tomcat执行FullGC时的影响

    下面我们看一下Apache的 MaxClients 参数在Full GC 发生时是如何影响系统的. 大部分开发人员都知道在由于GC发生而导致的”停止世界现象(STW) “(详细请参见Understan ...

  3. apache中 MaxClients 与MaxRequestsPerChild

    据现象来对APACHE调优,以前用MAXCLIENTS 3000,砖家建议后,改为1500,今天查资料如下: http://www.linuxqq.net/ MaxClients 要加到多少?连接数理 ...

  4. 在Apache Tomcat 7设置redis作为session store

    在Apache Tomcat 7设置redis作为session store  //输出tomcat控制台日志 root@ubuntu:~# cd /usr/tomcat/apache-tomcat- ...

  5. [Windows Server 2008] Apache+PHP安全设置

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:Win2008 ...

  6. [Windows Server 2012] Apache+PHP安全设置

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:Win20 ...

  7. apache环境.htaccess设置301跳转及常用.htaccess技巧整理

    apache环境.htaccess设置301跳转及常用.htaccess技巧整理 无论是Nginx,还是Apache都各自有优势,对于我们普通用户而言基本上也没有多大的区别.在虚拟主机环境中,基本上都 ...

  8. Linux课程---16、apache虚拟主机设置(如何在一台服务器上配置三个域名)

    Linux课程---16.apache虚拟主机设置(如何在一台服务器上配置三个域名) 一.总结 一句话总结:有三个网站www.lampym.com,bbs.lampym.com,mysql.lampy ...

  9. 【转】apache 二级域名设置完整步骤

    原文链接:http://blog.sina.com.cn/s/blog_5375d76b01014fnt.html 最近在折腾网站二级域名的事情,在网上查了很多零碎的文档,不完整,有些也没有自己验证, ...

随机推荐

  1. DRF的版本、认证、权限

    DRF的版本 版本控制是做什么用的, 我们为什么要用 首先我们要知道我们的版本是干嘛用的呢~~大家都知道我们开发项目是有多个版本的~~ 当我们项目越来越更新~版本就越来越多~~我们不可能新的版本出了~ ...

  2. 学习HashMap的笔记

    对于HashMap只是学习了下put,remove方法,hashMap是数组+链表+红黑树组成 所以下面贴出我自己给代码的注释,看不懂的见谅哈,毕竟我也是刚了解,如果有错误的地方请指出,非常感谢 pu ...

  3. sails ORM组件 Waterline v0.10 英文文档

    http://sailsdoc.swift.ren/ 这里有 sails中文文档 Introduction Installation Getting Started Models Data types ...

  4. django后台数据管理admin设置代码

    新建admin用户 createsuperuser 设定好用户名,邮箱,密码 设置setting LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shangha ...

  5. centOS7下安装laravel + composer

    1.wget https://dl.laravel-china.org/composer.phar -O /usr/local/bin/composer chmod a+x /usr/local/bi ...

  6. Ubuntu解压命令全览

    1. Ubuntu解压命令全览.tar 解包:tar xvf FileName.tar 打包:tar cvf FileName.tar DirName 注:tar是打包,不是压缩! .gz 解压1:g ...

  7. ruby中的链式访问和方法嵌套

    先看一道题,这道题是codewars上的一道题,我很早就看到了,但是不会写.等到又看到这道题的时候,我刚看完元编程那本书,觉得是可以搞定它的时候了.废话不多说,先看这道题,题目最开始是为JavaScr ...

  8. Mybatis 中 update 语句 动态 语句

    <update id="updateAdministrationAsset" parameterType="com.opple.fa.assetcard.entit ...

  9. Statement与PreparedStatement

    Statement 用于通用查询,能批处理 PreparedStatement(简称PS) 用于执行参数化查询,能批处理 什么是参数化查询? 指在设计与数据库链接并访问数据时,在需要填入数值或数据的地 ...

  10. 20145307第四次JAVA学习实验报告

    20145307实验四 Android开发基础 实验内容 基于Android Studio开发简单的 Android应用并部署测试; 了解Android组件.布局管理器的使用: 掌握Android中事 ...