跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
通过JVM性能调优启用基于Java的VoIP后端平台

时间:2006-07-03
作者:Bruno Van Den BosscheFilip De TurckPiet DemeesterBart Dhoedt
浏览次数:
本文关键字:WLCPvoipWebLogic Communications Platform调优JVMBruno Van Den Bossche
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章

  编者注:本文改编自发表在VoIP Mase '06 workshop学报(IEEE Catalog,Number 06EX1301)上的“Enabling Java-based VoIP backend platforms through JVM performance tuning”。

摘要

  在Voice over IP (VoIP)服务产品中,软件后端平台正日益变得重要。Java和J2EE平台已经发展成为在电信后端平台上设计和实现业务逻辑的重要软件框架。考虑到Java的流行,有人提出了这样一个问题:基于Java的后端平台能否满足VoIP应用程序的需求?

  会话发起协议(Session Initiation Protocol,SIP)是通常用于VoIP的重要信令协议。SIP Servlet技术被开发出来以构建基于Java的VoIP服务。本文将评估BEA Weblogic SIP Servlet实现的性能,介绍评估过程和所得到的结果,还将研究对Java虚拟机(JVM)进行调优所带来的影响。此外,根据所得到的结果,本文还将证明对于一般应用程序,以及更明确地对于VoIP相关应用程序,一些用于调整JVM以优化垃圾收集程序的技术的效果。

简介

  电信应用程序通常有非常严格的吞吐量(例如,一个软交换产品(soft switch)每秒处理的VoIP呼叫连接数)和延迟需求(例如,呼叫的建立必须非常快)。这些要求显示,Java可能不是用于此用途的好的选择,因为垃圾收集和虚拟机的行为可能会与这些严格的要求相冲突。

  Java语言是高度结构化的、强类型的和面向对象的。它不是被编译为特定于机器的指令,而是被编译为字节码,然后这些字节码将在各种平台上都有的虚拟机上执行。虽然这会造成一定的性能损失,但是这也使得Java具有高度的可移植性。另一个具有重要意义的特性是垃圾收集程序的使用。Java将自动化的内存管理(垃圾收集)作为Java运行时的一部分。这意味着以前开发人员常犯的一些与内存管理相关的错误都不会再出现了。由于垃圾收集功能成为Java运行时的一部分,不再是在应用程序开发人员的完全控制之下,所以这也造成了性能损失,并使得对垃圾收集的预测变得很复杂。

  为了使Java对电信行业更具吸引力,JAIN (Java APIs for Integrated Networks)提供了一组丰富的标准化API,用于方便电信服务的开发和部署。虽然JAIN确实提供了适用于电信应用程序的开放的标准化规范,但是它并没有直接解决Java垃圾收集的问题。本文将提出一些技术,用于根据特定的要求(比如:垃圾收集暂停时间和延迟的最小值,或者电信服务的总执行时间的最小值)帮助调优。

  首先我们将简要地说明一下所选择的用于性能评估的用例。接下来我们将解释一下相关的Java虚拟机内部结构,继之以可能的优化选项和调优技术。然后我们将概述测试设置和性能评估的结果。

SIP用例

  会话发起协议(SIP)描述了一个应用层控制(信令)协议,用于创建、修改和终止与一个或多个参与者的会话。这些会话包括Internet电话呼叫、多媒体分布和多媒体会议。

  下列Dev2Dev文章提供了对SIP、SIP Servlet和Weblogic Communications platform的更深入描述:

  图1显示了一个用于建立一个VoIP呼叫的典型用例,Proxy 200测试。本文选择它作为性能评估的例子。我们对它建立一个呼叫的时间感兴趣。下面就是从Alice发出初始INVITE(邀请)到她从Bob接收到OK所花费的时间。

图 1
图1. Proxy 200测试

  此后,Alice将向Bob发送一个确认,说明她接收到了OK,然后就可以开始媒体会话(media session)(例如,音频或视频会议)了。在进行基准测试时,不会启动媒体会话,呼叫会立即被终止。

Java虚拟机内部结构

  通常所使用的硬件平台会对性能和评估造成很大的影响,但是其实Java虚拟机也会产生很大影响。此处极为重要的因素是垃圾收集和内存管理。垃圾收集可能导致整个虚拟机暂停。在VOIP应用程序中,这些暂停不应该持续太长时间,因为在建立呼叫时,较长的暂停可能会导致超时。

Java虚拟机内存

  Java虚拟机的堆被分为3个称为generation的主要部分,它们对应于对象的生存期,如图2所示。3个generation分别是Young、Tenured和Perm,标记为Virtual的部分被保留,在必要时才实际分配出去。

  Young generation由Eden和两个survivor空间组成。新对象通常创建于Eden中。其中一个survivor空间会随时被清空,并用作另一个survivor空间的目的地。当进行垃圾收集时,所有来自Eden和survivor空间的活动对象都被复制到另一个survivor空间。对象在两个survivor空间之间移动,直到它们足够“老”,能够被移入保存生存期较长对象的tenured generation中。

  图 2
图2. Java虚拟机内存的结构

  Perm generation保存那些在虚拟机的整个生存期都生存的对象。因此,该generation不需要被垃圾收集程序清空。

Java垃圾收集策略

  除了默认的垃圾收集程序,还对其他的两个收集程序,Parallel收集程序和Concurrent Mark and Sweep收集程序(后面称为Concurrent收集程序)进行了评估。在标准的Sun Java运行时环境中,这些收集程序都可用。通常在进行垃圾收集时,虚拟机会暂停,让垃圾收集程序执行它的工作。Parallel收集程序会产生多个垃圾收集线程,以加速任务的执行并将垃圾收集暂停时间降至最短。该收集程序负责整理Young generation。Concurrent收集程序则负责整理tenured generation,而且会部分地与应用程序并发运行。虽然仍然需要完整的垃圾收集周期,但是整个周期会因之而缩短——虽然这是以牺牲少量处理能力为代价的,这些处理能力本来是可以由应用程序使用的。

  这两个收集程序可以一起使用,因为它们负责的是不同的generation。这将显著缩短由垃圾收集所引发的暂停时间,如图3所示。

  图 3
图3. 可用的垃圾收集程序

垃圾收集程序设置的优化

  由于改变参数后的影响并不总是能够被预料到,所以对垃圾收集的调优并不是一项简单的任务。这方面的白皮书并不少(参见“参考资料”部分),但是却缺乏对详细的(根据实验得到的)调优结果以及对垃圾收集的实际影响的描述。因此一个测试套件被开发出来,以便评估可能的优化,并暴露在设置不同的调优参数时可能出现的问题。本部分将探索调优过程,并涉及面向SIP信令特征的优化。

评估详情

  测试套件由一个可以生成特定数目的对象的应用程序组成,每个对象的生存期和在内存中的大小都可配置。该应用程序使用72种不同的虚拟机调优选项组合反复运行,这些选项包括堆大小的调整、generation大小的调整、垃圾收集程序的选择,以及以上各项的组合。我们根据经验并排除无关的参数组合来选择调优参数。我们使用一个基于开源的gcviewer应用程序的定制应用程序来观察和分析垃圾收集行为,它允许我们确定选项对垃圾收集所产生的精确影响。

  关于虚拟机调优,有两个重要的优化是可以做到的:总执行时间的最小化和由垃圾收集所引起的暂停时间的最小化。另一个选项是最小化花在执行垃圾收集操作上的总时间。在大多数情况下,这基本上等效于最小化总执行时间。然而,测试结果显示,也有例外的情况:虽然花在垃圾收集上的实际时间缩短了,总的执行时间也可能会变长。当将堆大小设置为一个固定或可变的值时,就会发生这种情况,如图4和5所示。在图中,如果使用单CPU,那么即使固定的堆可以缩短垃圾收集时间(固定的堆为10秒,可变的堆为17秒),它还是延长了总执行时间(405比403)。

  图 4
图4. 总垃圾收集时间

  图 5
图5. 总执行时间

  注意,该测试套件不是CPU限制(CPU-bound)型的,但是它按照特定的时间间隔分配对象。这意味着双CPU配置在垃圾收集方面处于有利地位,但是在执行时间方面没有大的区别。

被评估的选项

  下面是一个被评估的最重要选项的列表,附有简要描述:

   
-Xmx -Xms 这两个参数分别指定了虚拟机堆大小的最大值和最小值。通过设置最大值和最小值,可以指定固定的堆大小。有必要设置足够大的堆大小,以便虚拟机不会出现内存不足的情况,但如果堆大小设置得过大,垃圾收集时间就会不必要地延长。
-XX:+UseParNewGC 该选项启用可以与Concurrent收集程序同时运行的Parallel垃圾收集程序。
-XX:+UseConcMarkSweepGC 该选项启用Concurrent收集程序。

-XX:MaxNewSize
-XX:NewSize

这两个选项定义young generation的最大值和最小值。将young的大小设置为大于总堆大小的一半时会造成效率低下。如果设置得过小,又会因为young generation收集程序不得不频繁运行而造成瓶颈。
-XX:+UseTLAB 启用该选项时,虚拟机将支持对象的线程逻辑分配。这将允许多个线程并发地分配对象,而不太需要在共用的eden空间中进行锁定。

针对低延迟而进行优化

  当针对低延迟而进行优化时,最显而易见的Java垃圾收集程序选择应该是Parallel和Concurrent收集程序的组合,因为它们试图最小化垃圾收集进程的阻塞暂停时间。设置总的堆大小和young generation将会产生最好的结果,因为无需再花费时间重新调整它们的大小。但是,事实证明,要估算理想的大小是很困难的,而且也不可能找到一个对所有场景来说都是最优的“普遍适用的”值。因此下面的做法是明智的:只设置总的堆的最大值,确保在需要的时候有足够的内存空间可用。

  表1. 针对低延迟的Java虚拟机调优选项

  • -Xmx512m
  • -XX:+UseParNewGC
  • -XX:+UseConcMarkSweepGC
  • -XX:+UseTLAB
  • -XX:+CMSIncrementalMode
  • -XX:+CMSIncrementalPacing
  • -XX:CMSIncrementalDutyCycleMin=0
  • -XX:CMSIncrementalDutyCycle=10

  表1中所示的选项包括对Concurrent收集程序的微调(通过允许它以增量方式完成任务)。最好不要将堆的最大值设置得过大;考虑到平均垃圾收集暂停时间,增加堆大小的开销就不算大了。设置固定的堆大小确实会导致更长的垃圾收集暂停时间,如图6所示。

  图 6
图6. 经过低延迟优化后的垃圾收集暂停时间要短得多,尤其是当堆大小不固定时

  上面列表中最后4个垃圾收集选项只适用于具有一个或两个处理器的系统。这将启用并发标记扫描(concurrent mark and sweep,CMS)增量模式,它将收集程序的并发部分分成一组操作,而不是在一个线程中顺序地执行它们。对于小型系统来说,这需要认真考虑,因为收集程序的并发部分完全是使用一个CPU。让一个CPU专门用于处理可能很长的并发部分可能会产生严重的性能影响(例如,在响应时间和吞吐量方面)。操作组允许将CPU分配给夹在中间的应用程序。此外,这些操作组被安排在young收集之间,以便进一步减少垃圾收集的影响。

执行时间的最小化

  在优化执行时间时,消除由垃圾收集所引起的暂停就没那么重要了。然而,垃圾收集程序的并行执行仍然是可取的,因为一般情况下,这样会比默认的垃圾收集程序快。如果想最小化执行时间,通常最好是尽量减少垃圾收集次数,这可以通过设置一个更大的堆大小而做到。这将减少垃圾收集次数,但是会使垃圾收集时间变长,而且垃圾收集暂停时间会比使用低延迟选项时长。

  表2. 最小化执行时间的Java虚拟机调优选项

  • -Xmx1024m
  • -Xms1024m
  • -XX:+UseParNewGC
  • -XX:+UseTLAB

  表2显示了缩短执行时间的选项组。设置一个较大的固定堆大小会在使用默认的垃圾收集时造成严重的性能损失,但在使用Parallel垃圾收集程序时则会带来性能获益,如图7所示。

  图 7
图7. 在堆大小固定时,经过执行时间优化后的垃圾收集执行时间较短

特定的调优选项:SIP信令

  提出的这些选项组为根据特定的应用需求优化垃圾收集行为提供了一个好的基础。然而,在特定的情况下,还可以考虑使用一些其他的选项。一些应用程序,比如上面的SIP代理例子,具有允许进一步优化的特定行为:有许多对象的生存期非常短(例如,表示SIP消息的对象),而另一些对象的生存期则相当长(例如,表示SIP会话的对象)。为此,最好是把生存期较长的对象直接放入tenured空间,减少垃圾收集时对其进行评估的次数,从而加快垃圾收集进程。这被称为pretenuring(参见“参考资料”部分)。但是这需要来自虚拟机的支持,而这种支持目前无法获得。

  通过将对象在survivor空间之间进行复制的次数设置为零,我们可以获得类似的效果。现在对象仍然是在young generation中创建,但是如果它们生存得足够长,就会在进行young generation的第一次垃圾收集时,直接被转入tenured generation。这可以通过设置-XX:MaxTenuringThreshold=0选项来实现。作为一个结果,我们不再需要survivor空间了,因此survivor空间的大小应该减至最小。这可以通过设置-XX:SurvivorRatio=N选项来实现。因为只可以设置与young generation大小有关的大小,所以选择一个足够大的N值(如128)就可以获得我们想要的效果。要获得最优结果,我们推荐限制Young generation的大小。这将使垃圾收集执行得更为频繁,但是时间较短。

测试设置

  在讨论所得到的结果之前,我们将首先概述一下所使用的测试设置。

软件设置

  对于基准测试,我们使用SIPp。SIPp是一个用于SIP协议的免费开源测试工具/流量生成器。它可以生成SIP流量,建立和释放多个呼叫。它还可以阅读定制的XML scenario文件,描述从简单到复杂的呼叫流。它包括一些使用SIPstone定义的基本测试设置。本文中的所有测试使用的都是SIPp,并基于先前指定的场景。

硬件设置

  所运行的所有测试使用的都是dual Opteron 242 HP DL 145,将2GB的内存用作代理。客户端运行在AMD athlonXP 1600+机器上,通过100Mb以太交换网互联。所有平台运行的都是2.6内核的Debian GNU/Linux。使用Sun的JDK 1.4.2。

SIP Servlet性能结果

  现在我们可以来看一下测试结果了。前面几节介绍了Java虚拟机的内部结构、如何管理内存,以及当前可用的垃圾收集选项有哪些。此外,我们还介绍了如何调优这些选项以优化虚拟机和垃圾收集程序的行为。我们特别关注了对由垃圾收集所引起的暂停时间的最小化,因为它可能导致SIP呼叫的建立失败。现在我们将对BEA WebLogic SIP Servlet实现运行测试,看看这些因素综合作用的结果。

  对SIP Servlet容器运行一组测试来评估垃圾收集调优选项。在建立SIP呼叫时使用图1中所指定的场景,95%的呼叫INVITE消息的确认应该在50ms之内到达,而50%的呼叫应该在25ms之内到达。

  图8展示了只设置了最大堆大小、没有设置其它调优参数时的SIP Servlet应用服务器性能结果。其中明确显示,95个百分点从50个呼叫每秒(caps)就开始飞快上升。此时,多个SIP消息开始并发到达,这意味着一些消息在进行处理之前首先进行了排队。

  图 8
图8. 使用默认垃圾收集的SIP Servlet结果

  该结果的另一个问题是CPU使用率较低。在较高的呼叫率下,CPU使用率仍然较低,但是一些呼叫却超时了,这显然不是我们希望得到的结果。考虑到95%的呼叫应该在50ms之内响应,服务器的处理能力只能是130 caps。

  图9展示了使用表1中经低延迟优化后的选项和pretenuring选项所进行的测试的结果。首先可注意到的区别是,95%百分点的增长要慢得多了。虽然延迟仍然从70 caps开始增长,但是增长率不那么高了。因为平均垃圾收集暂停时间要比默认选项低得多,所以大部分呼叫的延迟不会太长。使用默认的垃圾收集选项,暂停时间高达1秒;而使用优化后的选项,暂停时间还不到10ms。

  图 9
图9. 使用优化后的垃圾收集调优的SIP Servlet结果

  其次,我们注意到,CPU使用率变高了,在250 caps时几乎达到100%。从这个呼叫率开始,有一些呼叫就开始超时了。幸运的是,响应时间也随之缩短了。显而易见,更先进的垃圾收集程序算法会需要更多的系统资源,但是它也会更好地完成任务。现在95%百分点的要求在240 caps才满足,比起默认的垃圾收集程序在130 caps达到,这个呼叫率明显要高得多。

  为了全面起见,还使用来自表2的最小化执行时间优化选项运行了初始测试。这些测试结果确实显示了比默认垃圾收集更低的延迟。但是,使用这些选项会导致垃圾收集暂停时间更长,这将使相当多的呼叫超时。在150 caps处,大约有10%的呼叫超时。得到处理的呼叫其响应时间确实在要求范围之内,但是10%的呼叫丢失率对于此类应用程序来说是不可接受的。不过,这些选项可能适用于其它具有不太严格要求的应用程序类型,或者是每个呼叫都尽快得到响应的要求并不那么重要的场景。

结束语

  目前,诸如SIP Servlet之类的Java技术可用于电信和IMS平台管理,简化管理和安全性实施,并可与现有系统进行平滑集成。本文显示,由Java虚拟机的垃圾收集程序所引起的性能问题可通过指定两组调优选项来解决,这两组选项要么改进了垃圾收集程序的延迟,要么最小化了总执行时间。

  由于VoIP应用程序在低延迟和高吞吐量方面有着非常严格的需求,我们使用了一个多媒体呼叫建立作为现实用例来验证所提出的优化。所得到的结果显示,如果对Java虚拟机进行适当的调优,Java和SIP Servlet是可以满足电信应用程序的低延迟需求的。

参考资料

原文出处:http://dev2dev.bea.com/pub/a/2006/05/voip-jvm-tuning.html

 作者简介
Bruno Van Den Bossche 是根特大学信息技术系的博士生。他的主要研究方向包括可伸缩的软件架构、分布式软件和软件的自动最优分发。
Filip De Turck 是根特大学信息技术系的兼职教授和F.W.O.-V.博士后成员。
Piet Demeester 是根特大学教授,他负责研究和讲授通信网络方面的内容。
Bart Dhoedt 任职于根特大学信息技术系。他的研究方向是软件工程和移动-无线通信。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分

   
相关产品