首页 | 联系我们 | 叶凡网络官方QQ群:323842844
游客,欢迎您! 请登录 免费注册 忘记密码
您所在的位置:首页 > 新闻中心 > 行业新闻 > 正文

名扬互联:JVM性能优化,Java的伸缩性

作者:cocomyyz 来源: 日期:2013-11-28 10:19:08 人气:0 加入收藏 评论:0 标签:

并且提供了并发压缩的垃圾回收算法,如果JVM做了这样的工作。JVM也不再成为Java可伸缩性的限制因素,Java应用开发者不需要花费痛苦的时间理解怎样配置JVM去获得最佳性能,从而将会有更多的有趣的Java应用层面的创新,而不是无休止的JVM调优。要挑战JVM开发人员以及提供商所 需要做的事情来响应甲骨文所提倡的MaketheJavaFutur活动。

花开了很多时间去调优应用顺序级别的性能瓶颈,很多顺序员在解决JVM性能问题的时候。当你读完这本系列文章之后你会发现我可能更加系统地看待这类的问题。说过JVM自身技术限制了Java企业级应用的伸缩性。首先我先列举一些主导因素。

l 主流的硬件服务器提供了大量的内存

而且该需求在继续增长l 分布式系统有大量内存的需求。

如下图所示(图中表述Java应用服务器和常规Java应用的内存使用量的演变史)l 一个普通Java应用顺序所持有的对空间大概在1GB~4GB这远远低于一个硬件服务器的内存管理能力以及一个分布式应用程序的内存需求量。这被称之为Java内存墙。

图 1Java内存墙(1980~2010

Java内存墙

Java内存墙

这给我带来了如下JVM性能课题:

将导致内存缺乏。JVM不能及时释放内存空间给应用程序,1   如果分配给应用程序的内存太小。最终将引发内存缺乏,或者JVM完全关闭。所以你必需提供更多的内存给应用程序。

如果不重启你系统或者优化你应用,2   如果给对响应时间敏感的应用增加内存。Java堆最终会碎片化。当碎片发生时,可能会导致应用中断100毫秒~100秒,这取决与你Java应用,Java堆的大小以及其他JVM调优参数。

很少涉及到堆压缩时的最坏停顿时间,关于停顿的讨论大部分都集中在平均停顿或者目标停顿。生产环境中堆中每千兆字节的有效数据的都将会发生大约1秒的停顿。

但实际只分配2~4GB内存。一 些64位系统中带有很多关于伸缩性的JVM调优项,2~4秒的停顿对大多数企业应用来说都是不能接受的所以尽管实际的Java应用实例可能需要更多的内存空间。使得这些系统可以运行16GB乃至20GB堆空间,并能满足典型响应时间的SLA 但是这些离现实较 远,JVM目前的技术无法在进行堆压缩时防止停顿应用顺序。Java应用开发人员苦于处置这两个为我大多数人所抱怨的任务。

随之而来的复杂的监控和管理操作。l 架构/建模在大量的实例池之上。

l 反复的JVM和应用顺序调优以避免“stoptheworld引起的停顿。大多数顺序员希望停顿不要发生在系统峰值负载期间。称之为不可能的目标。

现在让我深入一点Java可伸缩性问题。

过度供给或过度实例化Java安排

普通的做法是将Java应用安排在多个应用服务器实例上而不是一个或者少数应用服务器实例上。当一台Server上运行16个应用服务器实例可以充分利用所有的内存资源,为了充分利用内存资源。但如此无法解决的多实例的监控以及管理所带来的本钱,尤其是当你应用安排在多个Server上。

一台物理机上可能只不是不超过3个“大应用服务器实例”这样的布置更加不够经济也不够环保,另一个问题来了峰值负载时的内存资源不是每天都需要的这样就形成了巨大的浪费。有些情况下。尤其在非峰值负载期间。

下图中左边是多而小的应用服务器实例布置模式,让我来比较一下这两种部署架构。右边是少而大的应用服务器实例布置模式。两种模式处置同样的负载,究竟哪一种布置架构更具经济性。

图2大应用服务器布置场景

jvmperf5-fig2

上图源自:AzulSystems

而且可以突破JVM可伸缩性的限制。目前只有AzulZingJVM可以提供并发压缩的技术,如我之前说过的并发压缩使得大应用服务器布置模式变得可行。另外ZingServer侧的JVM很乐意看到越来越多的开发者在JVM层面去挑战Java可伸缩性的问题。

先来看有哪些主要的调优参数以及通过它能达到什么样的效果。由于性能调优仍然是解决Java可伸缩性问题的主要手段。

调优参数:一些事例

实际上可能不同的JVM执行结果不太一样。最著名的调优参数莫过于”-Xmx通过该参数可以指定Java堆空间大小。

垃圾回收器结构,有的JVM包括了内部结构(如编译器线程。代码缓存等等)所需要的内存在-Xmx设定中,而有的则不包含。因此用户Java进程的大小不一定跟“-Xmx设定相吻合。

对象的生命周期,如果你应用顺序分配对象的速率。或者对象的大小超越了JVM内存相关配置,一旦达到最大可使用内存的阈值将会发生内存溢出,用户进程则会停止。

最有效的方法就是通过”-Xmx指定更大的内存去重启当前应用进程。为了防止频繁的重启,当你应用顺序纠结于内存的可用性时。大多数企业生产环境都倾向于指定峰值负载时所需要的内存,造成过度配置优化。

提示:生产环境负载的调整

移植到生产环境是忘记重新调整。生产环境和实验室环境是不一样的谨记根据生产环境的负载重新调整堆内存设置。Java开发人员易犯的罕见错误是实验下的做的堆内存设置。

分代垃圾回收器调优

用来指定堆中专门负责新对象分配的空间大小。还有一些其他优化选项”-Xn和”-XX:NewSiz用来调整年轻代的大小。

这意味着在生产负载下存在失败的风险。一般新生代的大小设置为堆大小的三分之一至二分之一左 右,大多数开发者都试图基于实验室环境调整年轻代的大小。但这不是一个准则,终究实际还要视应用顺序逻辑而定。因此最好先调查清楚年轻代到年老代的蜕变率以及年老代对象的大小,此基础上(确保年老代的大 小,年老代过小会频繁促发GC导致内存溢出错误)尽可能地调大年轻代的空间。

逾越指定时长相关对象将被移至年老 代。为了正确”地设定该值,还有一个与年轻代相关的调优项”-XX:SurvivorRatio该选项用来指定年轻代中对象的生命周期。需要知道年轻代空间回收的频率,能够估算到新对象在应用顺序进程中被引用的时长,同时也取决于分配率。

并发垃圾回收调优

建议使用并发垃圾回收,虽然并行的方法能够带来非常好的吞吐量基准测试分数,但是并行GC有利于缩短响应时间。并发 GC目前唯一有效的实现一致性和最少“stoptheworld中断的方法。不同的JVM提供不同的并发GC设定,OraclJVMhotspot提供”-XX:+UseConcMarkSweepGC,针对对停顿敏感的应用。今后G1将成为OraclJVM默认的并发垃圾回收器。

性能调优并不是真正的解决方法

刻意在正确“二字上加了双引号。那是因为就我个人经验而言一旦涉及到性能参数调 优,或许你已经注意到上文中在讨论如何“正确“地设定调优此参数时。就没有严格意义上的正确设定。每一个设定值都是针对特定的场景。考虑到应用场景会发生变化,JVM性能调整充其量是一个权宜之计。

但是可能不能应付40万的并发用户。以堆的设置为例:如果2GB堆可以应对20万并发用户。

当压力到达每毫秒50000个交易时又会发生什么呢?再以”-XX:SurvivorRatio为例:当设定符合一个负载继续增长最高至每毫秒10000个交易的场景。

大多数企业级应用负载都是动态的Java语言的动态内存管理以及动态编译等技术使得Java更加适合企业级应用。来看看一下两个配置清单。

清单1.应用顺序(1启动选项

  >java-Xmx12g-XX:MaxPermSize=64M-XX:PermSize=32M-XX:MaxNewSize=2g

   

  -XX:NewSize=1g-XX:SurvivorRatio=16-XX:+UseParNewGC

   

  -XX:+UseConcMarkSweepGC-XX:MaxTenuringThreshold=0

   

  -XX:CMSInitiatingOccupancyFraction=60-XX:+CMSParallelRemarkEn

   

  -XX:+UseCMSInitiatingOccupancyOnli-XX:ParallelGCThreads=12

   

  -XX:LargePageSizeInBytes=256m

清单 2.应用顺序(2启动选项

  >java–Xms8g–Xmx8g–Xmn2g-XX:PermSize=64M-XX:MaxPermSize=256M

   

  -XX:-OmitStackTraceInFastThrow-XX:SurvivorRatio=2-XX:-UseA daptiveSizePolici-XX:+UseConcMarkSweepGC

   

  -XX:+CMSConcurrentMTEn-XX:+CMSParallelRemarkEn-XX:+CMSParallelSurvivorRemarkEn

   

  -XX:CMSMaxA bortablePrecleanTime=10000-XX:+UseCMSInitiatingOccupancyOnli

   

  -XX:CMSInitiatingOccupancyFraction=63-XX:+UseParNewGC–Xnoclassgc

因为他两个不同应用顺序。感觉根据各自的应用特设都做了正确“配置与调优。实验室环境下都运行良好,两者的配置区别很大。但在生产环境中 最终会表示出疲态。清单1由于没有考虑到动态负载,生产环境即表现不良。清单2没有考虑到应用顺序在生产环境中的特性变化。这两种情况应该归咎于开发 团队,但是该归咎于何处呢?

变通方法可行吗?

防止内存压缩的场景。这两种方法都可以,有些企业通过精确丈量交易对象的大小定义极致的对象回收空间并”精简“其架构来适配该空间。这也许是方法来削减碎片以应对一整天的交易(不做堆压 缩的情况下)还有一个办法就是通过顺序设计确保对象被引用的时间在一个比较短的时间内从而阻止其在SurvivorRatio时间之后不被迁往年老代而 直接被回收。但是对应用开发人员和设计人员有一定的挑战。

谁保证应用顺序的性能?

开发团队就会受到责备。也许某些场所下开发团队应该要受到责备,一个门户应用可能会在其活动负载峰值点出现故障;一个交易应用可能会在每次市场下跌和上升时无法正常运行;电子商务网站可能会无法应对节假日购物高 峰期。这些都是真实世界的案例基本都是JVM性能参数调优导致的当产生了经济损失。但是JVM提供商又应该负起什么样儿的责任呢?

至少这在短期内还是很有意义的有一些新的调优选项是针对特定的新兴的企业应用顺序场景。更多的调优选项是为了减轻JVM支持团队的工作负荷而将性能优化转嫁到应用开发者身上。但我个人认为这或将导致更加漫长的支持负 荷,首先JVM提供商应该要提供调优参数的优先顺序。一些针对最糟糕场景的调优选项也将被延期,当然不是无限延期。

同时也只有应用实施者才会更加清楚他应用的特定需求。但是应用的实施者或开发者是无法预测 期动态的负载需求。过去,毋庸置疑JVM开发团队也在努力地进行着他工作。JVM提供商也会去分析关于Java性能与可扩展性问题,哪些是能够解决的不是提供调优参数,而是直接去优化或创新垃 圾回收的算法。更有趣是可以想象一下如果OpenJDK社区聚集在一起重新考虑Java垃圾回收器将会发生什么!

JVM性能的基准测试

因为不同的调优可以改善他JVM可预见的环境中的性能表示,调优参数有时被JVM提供商作为其竞争的工具。本系列的最后一片文章中将调查这些基准测试来衡量JVM性能。

JVM开发者的挑战

因此是时候号召我Java开发者社区来迎接真正的Java可伸缩性的挑战。真正的企业级可伸缩性需求是要求JVM能够适应动态灵活的应用负载。这是特定吞吐量和响应时间内保证继续稳定性能的关键。这是JVM开发者才干完成历史使命。

  l 继续调优

一开始需要告知其需要多大的内存,对于给定的应用。之后的工作都应该有JVM来负责 JVM需要适配动态的应用负载和运行场景。

  l JVM实例数 vs.实例的可扩展性

那么为什么JVM实例不能有效地利用它呢?将应用拆分部署许多小的应用服务器实例上,现在服务器都支持很大的内存。这从经济和环保角度都是一种浪费。现代的JVM需要跟上硬件和应用的发展潮流。

  l 真实世界的性能和可伸缩性

企业不需要为其应用的性能需求去做极致的性能调优。JVM提供商和OpenJDK社区需要去解决Java可伸缩性的核心问题以及消除“stoptheworld操作。

结论


本文网址:http://www.mingyangnet.com/html/hangye/1125.html
读完这篇文章后,您心情如何?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
更多>>网友评论
发表评论
编辑推荐
  • 没有资料