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

JVM调优案例分析与实战(1):高性能硬件上的程序部署策略

本JVM系列均来源于《深入理解Java虚拟机》一书中,摘抄在此以便学习,版权归该书作者所有。环境:一个15万PV天左右的在线文档类型网站最近更换了硬件系统,新系统硬件为4个CPU、

>本JVM系列均来源于《深入理解Java虚拟机》一书中,版权归该书作者所有。

>环境:一个15万PV/天左右的在线文档类型网站最近更换了硬件系统,新系统硬件为4个CPU、16GB物理内存、OS为64位CentOS5.4、Resin作为Web服务器。

>说明:整个服务暂时没有部署别的应用,所有硬件资源都可以提供给访问量并不算太大的网站使用。管理员为了尽量利用硬件资源选用了64位的JDK1.5,并通过-Xmx和-Xms参数将java堆固定在12GB。

>问题:使用一段时间后发现使用效果并不理想,网站经常不定期出现长时间没有响应的现象。

>排查:监控服务器运行状况后发现网站没有响应是由于GC停顿导致的,虚拟机运行在Server模式,默认使用吞吐量优先收集器,回收12GB的堆,一次Full
GC的停顿时间高达14s。并且由于程序设计的关系,访问文档时要把文档从磁盘提取到内存中,

       
导致内存中出现很多由文档序列化产生的大对象,这些大对象很多都进入了
>老年代,没有在Minor
GC中清理掉。这种情况下即使有12GB的堆,内存也很块被消耗殆尽,由此导致每隔十几分钟出现十几秒的停顿。

>分析:先不延伸讨论程序代码问题,程序部署上主要问题显然是过大的堆内存进行回收时带来的长时间停顿。硬件升级前使用32位系统1.5GB的堆,用户只感到访问网站比较缓慢,但不会发生十分明显的停顿,因此才考虑升级硬件来提升程序效能,如果重新

>       
缩小给java堆分配的内存,那么硬件上的投资就浪费了。

>        >在高性能硬件上部署程序,目前主要有两种方式:1.通过64为JDK来使用大内存
2.使用若干个32位虚拟机建立逻辑集群来利用硬件资源

>       
此案例中管理员采用了第一种部署方式。对于用户交互性强、对停顿时间敏感的系统,可以给Java虚拟机分配超大堆的前提是有把握把应用程序的Full
GC频率控制得足够低,至少要低到不会影响用户使用,譬如十几个小事乃至一天才出现一次Full GC,这样可以通过在深夜执行定时任务的方式触发Full
GC甚至自动重启服务器来将内存可用空间保持在一个稳定的水平。

>       
控制Full
GC频率的关键是看应用中绝大多数对象能否符合“招生夕灭”的原则,即大多数对象的生存时间不应太长,尤其是不能产生批量的、长生存时间的大对象,这样才能保证老年代空间的稳定。

>       
在大多数网站形式的应用里,主要对象的生存周期都应该是请求级或页面级的,回话级和全局级的长生命对象相对减少。只要代码写得合理,应当都能实现在超大堆中正常使用而没有Full
GC,这样的话,使用超大堆内存时,网站响应的速度才比较有保证。除此之外,如果读者计划使用64位JDK来管理大内存,还需要考虑下面可能面临的问题:

>       
1.内存回收导致的长时间停顿

>       
2.现阶段,64位JDK的性能测试结果普遍低于32位JDK。

>       
3.需要保证程序足够稳定,因为这种应用要是产生堆溢出几乎无法产生>堆转储快照(因为要产生十几GB乃至更大的dump文件),哪怕产生了快照也几乎无法进行分析。

>       
4.相同的程序在64位JDK中消耗的内存一般比32位JDK大,这是由于指针膨胀及数据型对齐补白等因素导致的。

>       
上面的问题听起来有点吓人,所以现价段不少管理员还是选择了第二种方式:使用若干个32位虚拟建立逻辑集群>来利用硬件资源。具体做法是在一台物理机器上启动多个应用服务器进程,给每个服务器进行分配不同的端口,然后在前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。读者不需要太在意均衡器转发所消耗的性能,即使使用64位JDK,许多应用也不止有一台服务器,因此许多应用中前段的均衡器总是要存在的。

>>      
考虑到一台物理机器上建立逻辑集群的目的仅仅是尽可能地利用硬件资源,并不需要关心状态保留、热转移之类的高可用性需求,也不需要保证每个虚拟机进程有绝对准确的均衡负载,因此使用无Session复制的亲合式集群是一个相当不错的选择。我们仅仅需呀保障集群具备亲和性,也就是均衡器按一定的规则算法(一般根据SessionID分配)将一个固定的用户请求永远分配到固定的一个集群节点进行处理即可,这样程序开发阶段就基本不用为集群环境做什么特别的考虑。

>>     
当然,很少有没有缺点的方案,如果读者计划使用逻辑集群的方式来部署程序,可能会遇到下面的一些问题。

>>     
1.尽量避免节点竞争全局资源,最典型的就是磁盘竞争,各个节点如果同时访问某个磁盘文件的话(尤其是并发写操作容易出现问题),很容易导致IO异常。

>>     
2.很难最高效率地利用某些资源池,如连接池,一般都是在各个节点建立自己独立的连接池,这样有可能导致一些节点池满了而另外一些节点仍有较多空余。尽管可以使用集中式的JNDI,但这有一定的复杂性且可能带来额外的性能代价。

>>     
3.各个节点仍然不可避免地受到32位的内存限制,在32位Windows平台中每个进程只能使用2GB的内存,考虑到堆以外的内存开销,堆一般最多只能开到1.5GB。在某些Linux,Unix系统(如Solaris)中,可以提升到3GB乃至接近4GB的内存,但32位

>>        
中仍然受最高4GB(2^32)内存的限制。

>>     
4.大量使用本地缓存(如大量使用HashMap所谓K/V缓存)的应用,在逻辑集群中会造成较大的内存浪费,因为每个逻辑节点上都有一份缓存,这时可以考虑把本地缓存改成集中式缓存

>>     
介绍完这两种部署方式,再重新回到这个案例中,最后的部署方案调整为建立5个32位JDK的逻辑集群,每个进程按2GB内存计算(其中堆固定为1.5GB),占用了10GB的内存。另外建立一个Apache服务作为前端均衡器代理访问门户。考虑到用户对响应较低,因此改为CMS收集器进行垃圾回收。部署方式调整后,服务再没有出现长时间停顿,速度比硬件升级前有较多提升。


推荐阅读
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
author-avatar
炫彩十字绣I_775
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有