热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaGC(4)Apache的MaxClients参数详解及Tomcat执行FullGC的影响

在第一篇文章中,我们学习了不同GC算法的执行过程,GC如何工作,新生代及老年代的基本概念,在JDK7中你应该了解的5种GC类

       在第一篇文章中,我们学习了不同GC算法的执行过程,GC如何工作,新生代及老年代的基本概念,在JDK7中你应该了解的5种GC类型以及他们的性能如何。第二篇文章中,我们学到了JVM到底是如何执行垃圾回收,我们如何监控GC,以及那些工具可以使得监控过程更高效。第三篇文章中,我们通过实际的例子学到了一些可以优化GC的参数。同时我们讲解了如何减少对象被转移到老年代空间,如何缩短Full GC时间,以及如何设置GC类型及内存空间。本篇文章中,我们将阐述Apache中MaxClients 参数的重要性,以及他如何在GC发生时,显著地影响整个系统的性能。我们将提供几个例子以方便你理解MaxClients 导致的问题。同时我们还会说明如何根据系统的内存情况,设置最佳的MaxClients参数值。

1、MaxClients对于系统的影响

        大部分开发人员都知道,由于GC发生而导致的”停止世界现象(STW) ”。尤其是,Java开发人员也经常会遇到由于GC原因导致的Tomcat报错。由于Java 虚拟机 (JVM)管理着内存,以Java为基础的程序无法摆脱GC导致的STW现象。假如在某一个时间,当你正在操作你开发的应用时,GC开始执行。即使TTS错误没有发生,你的服务也会给客户展现未预期的503错误。

2、服务执行环境

       由于架构本身的特点,相比较纵向扩展,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

3、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)。

4、MaxClients 与backlog

        在这种情况下,设定哪个参数可以避免返回给用户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进程数量暴增,引发内存交换,降低系统性能。

5、MaxClients参数的计算公式

         如果系统的内存是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。

6、总结

      一个健壮的服务配置至少应该能够降低在服务过载时宕机的时间,在合理的范围内成功的应答请求。针对基于Java的Web服务。你必须检查你的服务在Full GC导致的STW时间内能否稳定的响应请求。为了响应更多的用户请求和应对DDoS攻击,在没有全面考虑系统内存等因素的情况下,贸然地将 MaxClients设置为一个很大的值,那么它将失去作为阀值的功能,而导致系统出现更严重的问题。本文提到的情况只会持续3-5秒,因此绝大多数传统的监控工具都无法及时的发现。



推荐阅读
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • Java能否直接通过HTTP将字节流绕过HEAP写入SD卡? ... [详细]
  • 在日常的项目开发中,测试环境和生产环境通常采用HTTP协议访问服务。然而,从浏览器的角度来看,这种访问方式会被标记为不安全。为了提升安全性,当前大多数生产环境已经转向了HTTPS协议。本文将详细介绍如何在Spring Boot应用中配置SSL证书,以实现HTTPS安全访问。通过这一过程,不仅可以增强数据传输的安全性,还能提高用户对系统的信任度。 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • 本文详细探讨了Zebra路由软件中的线程机制及其实际应用。通过对Zebra线程模型的深入分析,揭示了其在高效处理网络路由任务中的关键作用。文章还介绍了线程同步与通信机制,以及如何通过优化线程管理提升系统性能。此外,结合具体应用场景,展示了Zebra线程机制在复杂网络环境下的优势和灵活性。 ... [详细]
  • 本文探讨了利用Java实现WebSocket实时消息推送技术的方法。与传统的轮询、长连接或短连接等方案相比,WebSocket提供了一种更为高效和低延迟的双向通信机制。通过建立持久连接,服务器能够主动向客户端推送数据,从而实现真正的实时消息传递。此外,本文还介绍了WebSocket在实际应用中的优势和应用场景,并提供了详细的实现步骤和技术细节。 ... [详细]
  • CSS3 @font-face 字体应用技术解析与实践
    在Web前端开发中,HTML教程和CSS3的结合使得网页设计更加多样化。长期以来,Web设计师受限于“web-safe”字体的选择。然而,CSS3中的`@font-face`规则允许从服务器端加载自定义字体,极大地丰富了网页的视觉效果。通过这一技术,设计师可以自由选择和使用各种字体,提升用户体验和页面美观度。本文将深入解析`@font-face`的实现原理,并提供实际应用案例,帮助开发者更好地掌握这一强大工具。 ... [详细]
  • 深入浅析JVM垃圾回收机制与收集器概述
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。 ... [详细]
  • 在JavaScript中,定位属性是理解元素布局的关键。本文通过详细的图示解析,介绍了这些属性的基础概念。以`clientHeight`为例,它表示元素的可见内容区域高度,不包括边距(margin)、边框(border)和滚动条。同样,`clientWidth`则表示元素的可见内容区域宽度。这些属性对于精确控制页面元素的尺寸和位置至关重要。 ... [详细]
  • 算法学习心得与经验总结
    在算法学习的过程中,我总结了一些宝贵的心得和经验。本文将重点探讨莫比乌斯反演技巧的应用,并提供详细的实例解析。通过不断的学习和实践,我逐步掌握了这一复杂但强大的工具。此外,文章还将分享一些实用的学习资源和参考资料,帮助读者更好地理解和应用这些算法。希望本文能为算法学习者提供有价值的参考和指导。 ... [详细]
  • CAS 机制下的无锁队列设计与实现 ... [详细]
  • 实现Nginx对ThinkPHP URL重写及PATHINFO支持的详细方法解析【PHP开发】
    在PHP后端开发中,实现Nginx对ThinkPHP的URL重写及PATHINFO支持是一项常见的需求。本文详细解析了经过多次尝试和研究,最终找到的一种有效配置方法,能够确保URL_MODERewrite功能正常运行,并提供稳定的服务。此外,文章还探讨了相关配置项的具体作用及其优化建议,帮助开发者更好地理解和应用这些技术。 ... [详细]
author-avatar
潮人搭配师er氵ic_161
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有