JVM性能优化,Java的伸缩性_可伸缩性.docx
《JVM性能优化,Java的伸缩性_可伸缩性.docx》由会员分享,可在线阅读,更多相关《JVM性能优化,Java的伸缩性_可伸缩性.docx(26页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、JVM性能优化,Java的伸缩性_可伸缩性 许多程序员在解决JVM性能问题的时候,花开了许多时间去调优应用程序级别的性能瓶颈,当你读完这本系列文章之后你会发觉我可能更加系统地看待这类的问题。我说过JVM的自身技术限制了Java企业级应用的伸缩性。首先我们先列举一些主导因素。 l 主流的硬件服务器供应了大量的内存 l 分布式系统有大量内存的需求,而且该需求在持续增长 l 一个一般Java应用程序所持有的对空间也许在1GB4GB,这远远低于一个硬件服务器的内存管理实力以及一个分布式应用程序的内存需求量。这被称之为Java内存墙,如下图所示(图中表述Java应用服务器和常规Java应用的内存运用量的
2、演化史)。 图 1 Java内存墙(110102022) Java内存墙 这给我们带来了如下JVM性能课题: 1) 假如安排给应用程序的内存太小,将导致内存不足。JVM 不能刚好释放内存空间给应用程序,最终将引发内存不足,或者JVM完全关闭。所以你必需供应更多的内存给应用程序。 2) 假如给对响应时间敏感的应用增加内存,假如不重启你的系统或者优化你的应用,Java堆最终会碎片化。当碎片发生时,可能会导致应用中断101毫秒101秒,这取决与你的Java应用,Java堆的大小以及其他的JVM调优参数。 关于停顿的探讨大部分都集中在平均停顿或者目标停顿,很少涉及到堆压缩时的最坏停忽然间,在生产环境中
3、堆中每千兆字节的有效数据的都将会发生大约1秒的停顿。 24秒的停顿对大多数企业应用来说都是不能接受的,所以尽管实际的Java应用实例可能须要更多的内存空间,但实际只安排24GB的内存。在一 些64位系统中带有许多关于伸缩性的JVM调优项,使得这些系统可以运行16GB乃至20GB的堆空间,并能满意典型响应时间的SLA。但是这些离现实较 远,JVM目前的技术无法在进行堆压缩时避开停顿应用程序。Java应用开发人员苦于处理这两个为我们大多数人所埋怨的任务。 l 架构/建模在大量的实例池之上,随之而来的是困难的监控和管理操作。 l 反复的JVM和应用程序调优以避开stop the world引起的停顿
4、。大多数程序员希望停顿不要发生在系统峰值负载期间。我称之为不行能的目标。 现在让我们深化一点Java的可伸缩性问题。 过度供应或过度实例化Java部署 为了充分利用内存资源,一般的做法是将Java应用部署在多个应用服务器实例上而不是一个或者少数应用服务器实例上。当一台Server上运行16 个应用服务器实例可以充分利用全部的内存资源,但如此无法解决的是多实例的监控以及管理所带来的成本,尤其是当你的应用部署在多个Server上。 另一个问题来了,峰值负载时的内存资源不是每天都须要的,这样就形成了巨大的奢侈。有些状况下,一台物理机上可能只不是不超过3个大应用服务器实例,这样的部署更加不够经济也不够
5、环保,尤其在非峰值负载期间。 让我们来比较一下这两种部署架构,下图中左边是多而小的应用服务器实例部署模式,右边是少而大的应用服务器实例部署模式。两种模式处理同样的负载,原委哪一种部署架构更具经济性。 图2 大应用服务器部署场景 上图源自:Azul Systems 如我之前说过的,并发压缩使得大应用服务器部署模式变得可行,而且可以突破JVM可伸缩性的限制。目前只有Azul的Zing JVM可以供应并发压缩的技术,另外Zing是Server侧的JVM,我们很乐意看到越来越多的开发者在JVM层面去挑战Java可伸缩性的问题。 由于性能调优仍旧是我们解决Java可伸缩性问题的主要手段,我们先来看有哪些
6、主要的调优参数以及通过它们能达到什么样的效果。 调优参数:一些事例 最闻名的调优参数莫过于-Xmx了,通过该参数可以指定Java的堆空间大小,事实上可能不同的JVM执行结果不太一样。 有的JVM包含了内部结构(如编译器线程,垃圾回收器结构,代码缓存等等)所须要的内存在-Xmx的设定中,而有的则不包含。因此用户Java进程的大小不肯定跟-Xmx的设定相吻合。 假如你的应用程序安排对象的速率,对象的生命周期,或者对象的大小超过了JVM内存相关配置,一旦达到最大可运用内存的阈值将会发生内存溢出,用户进程则会停止。 当你的应用程序纠结于内存的可用性时,最有效的方法就是通过-Xmx指定更大的内存去重启当
7、前应用进程。为了避开常见的重启,大多数企业生产环境都倾向于指定峰值负载时所须要的内存,造成过度配置优化。 提示:生产环境负载的调整 Java开发人员易犯的常见错误是在试验下的做的堆内存设置,在移植到生产环境是遗忘重新调整。生产环境和试验室环境是不一样的,谨记依据生产环境的负载重新调整堆内存设置。 分代垃圾回收器调优 还有一些其他的优化选项-Xns和-XX: NewSize,用来调整年轻代的大小,用来指定堆中特地负责新对象安排的空间大小。 大多数开发者都试图基于试验室环境调整年轻代的大小,这意味着在生产负载下存在失败的风险。一般新生代的大小设置为堆大小的三分之一至二分之一左 右,但这不是一个准则
8、,终归实际还要视应用程序逻辑而定。因此最好先调查清晰年轻代到年老代的蜕变率以及年老代对象的大小,在此基础上(确保年老代的大 小,年老代过小会频繁促发GC导致内存溢出错误)尽可能地调大年轻代的空间。 还有一个与年轻代相关的调优项-XX:SurvivorRatio,该选项用来指定年轻代中对象的生命周期,超过指定时长相关对象将被移至年老 代。为了正确地设定该值,你须要知道年轻代空间回收的频率,能够估算到新对象在应用程序进程中被引用的时长,同时也取决于安排率。 并发垃圾回收调优 针对对停顿敏感的应用,建议运用并发垃圾回收,虽然并行的方法能够带来特别好的吞吐量基准测试分数,但是并行GC不利于缩短响应时间
9、。并发 GC 是目前唯一有效的实现一样性和最少stop the world中断的方法。不同的JVM供应不同的并发GC的设定,Oracle JVM(hotspot)供应-XX:+UseConcMarkSweepGC,今后G1将成为Oracle JVM默认的并发垃圾回收器。 性能调优并不是真正的解决方法 或许你已经留意到上文中在探讨如何正确地设定调优此参数时,我刻意在正确二字上加了双引号。那是因为就我个人阅历而言一旦涉及到性能参数调 优,就没有严格意义上的正确设定。每一个设定值都是针对特定的场景。考虑到应用场景会发生改变,JVM 性能调整充其量是一个权宜之计。 以堆的设置为例:假如2GB的堆可以应
10、对20万并发用户,但是可能不能应付40万的并发用户。 我们再以-XX:SurvivorRatio为例:当设定符合一个负载持续增长最高至每毫秒10100个交易的场景,当压力到达每毫秒50000个交易时又会发生什么呢? 大多数企业级应用负载都是动态的,Java语言的动态内存管理以及动态编译等技术使得Java更加适合企业级应用。我们来看看一下两个配置清单。 清单1. 应用程序(1)的启动选项 >java -Xmx12g -XX:MaxPermSize=64M -XX:PermSize=32M -XX:MaxNewSize=2g -XX:NewSize=1g -XX:SurvivorRatio=
11、16 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:MaxTenuringThreshold=0 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:ParallelGCThreads=12 -XX:LargePageSizeInBytes=256m 清单 2. 应用程序(2)的启动选项 >java –Xms8g –Xmx8g –Xmn2g -XX:
12、PermSize=64M -XX:MaxPermSize=256M -XX:-OmitStackTraceInFastThrow -XX:SurvivorRatio=2 -XX:-UseAdaptiveSizePolicy -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled -XX:+CMSParallelRemarkEnabled -XX:+CMSParallelSurvivorRemarkEnabled -XX:CMSMaxAbortablePrecleanTime=10100 -XX:+UseCMSInitiatingOccupancy
13、Only -XX:CMSInitiatingOccupancyFraction=63 -XX:+UseParNewGC –Xnoclassgc 两者的配置区分很大,因为他们是两个不同应用程序。感觉依据各自的应用特设都做了正确的配置与调优。在试验室环境下都运行良好,但在生产环境中 最终会表现出疲态。清单1由于没有考虑到动态负载,到了生产环境即表现不良。清单2没有考虑到应用程序在生产环境中的特性改变。这两种状况应当归咎于开发 团队,但是该归咎于何处呢? 变通方法可行吗? 有些企业通过精确测量交易对象的大小定义极致的对象回收空间并精简其架构来适配该空间。这或许是方法来削减碎片以应对一成天
14、的交易(在不做堆压 缩的状况下)。还有一个方法就是通过程序设计确保对象被引用的时间在一个比较短的时间内从而阻挡其在SurvivorRatio时间之后不被迁往年老代而 干脆被回收,避开内存压缩的场景。这两种方法都可以,但是对应用开发人员和设计人员有肯定的挑战。 谁保障应用程序的性能? 一个门户应用可能会在其活动负载峰值点出现故障;一个交易应用可能会在每次市场下跌和上升时无法正常运行;电子商务网站可能会无法应对节假日购物高 峰期。这些都是真实世界的案例基本都是JVM性能参数调优导致的。当产生了经济损失,开发团队就会受到责怪。或许某些场合下开发团队应当要受到责怪,但是 JVM的供应商又应当负起什么样
15、儿的责任呢? 首先JVM供应商应当要供应调优参数的优先依次,至少这在短期内还是很有意义的。有一些新的调优选项是针对特定的、 新兴的企业应用程序场景。更多的调优选项是为了减轻JVM支持团队的工作负荷而将性能优化转嫁到应用开发者身上。但我个人认为这或将导致更加漫长的支持负 荷,一些针对最糟糕场景的调优选项也将被延期,当然不是无限延期。 毋庸置疑JVM的开发团队也在努力地进行着他们的工作,同时也只有应用实施者才会更加清晰他们应用的特定需求。但是应用的实施者或开发者是无法预料 期动态的负载需求。在过去,JVM供应商也会去分析关于Java的性能与可扩展性问题,哪些是他们能够解决的。不是供应调优参数,而是
16、干脆去优化或创新垃 圾回收的算法。更好玩是我们可以想象一下假如OpenJDK的社区聚集在一起重新考虑Java垃圾回收器将会发生什么! JVM性能的基准测试 调优参数有时被JVM供应商作为其竞争的工具,因为不同的调优可以改善他们的JVM在可预见的环境中的性能表现,本系列的最终一片文章中将调查这些基准测试来衡量JVM的性能。 JVM开发者的挑战 真正的企业级可伸缩性需求是要求JVM能够适应动态敏捷的应用负载。这是在特定吞吐量和响应时间内保证持续稳定性能的关键。这是JVM开发者才能完成历史使命,因此是时候号召我们Java开发者社区来迎接真正的Java可伸缩性的挑战。 l 持续调优 对于给定的应用,在
17、一起先须要告知其须要多大的内存,之后的工作都应当有JVM来负责 ,JVM须要适配动态的应用负载和运行场景。 l JVM实例数 vs. 实例的可扩展性 现在的服务器都支持很大的内存,那么为什么JVM实例不能有效地利用它呢?将应用拆分部署很多小的应用服务器实例上,这从经济和环保角度都是一种奢侈。现代的JVM须要跟上硬件和应用的发展潮流。 l 真实世界的性能和可伸缩性 企业不须要为其应用的性能需求去做极致的性能调优。JVM供应商和OpenJDK社区须要去解决Java可伸缩性的核心问题以及消退stop the world的操作。 结论 假如JVM做了这样的工作,并且供应了并发压缩的垃圾回收算法,JVM
18、也不再成为Java可伸缩性的限制因素,Java应用开发者不须要花费苦痛的 时间理解怎样配置JVM去获得最佳性能,从而将会有更多的好玩的Java应用层面的创新,而不是无休止的JVM调优。我要挑战JVM开发人员以及供应商所 须要做的事情来响应甲骨文所提倡的Make the Java Future的活动。 关于作者 Eva Andearsson对JVM技术、SOA、云计算和其他企业级中间件解决方案有着10多年的从业阅历。在2001年,她以JRockit JVM开发者的身份加盟了创业公司Appeal Virtual Solutions(即BEA公司的前身)。在垃圾回收领域的探讨和算法方面,EVA获得了
19、两项专利。此外她还是提出了确定性垃圾回收 (Deterministic Garbage Collection),后来形成了JRockit实时系统(JRockit Real Time)。在技术上,Eva与SUN公司和Intel公司合作亲密,涉及到许多将JRockit产品线、WebLogic和Coherence整合的项 目。2022年,Eva加盟了Azul System公,担当产品经理。负责新的Zing Java平台的开发工作。最近,她改换门庭,以高级产品经理的身份加盟Cloudera公司,负责管理Cloudera公司Hadoop分布式系统,致力于高扩展性、分布式数据处理框架的开发。 许多程序员在
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JVM 性能 优化 Java 伸缩性
限制150内