本教程是一个教程系列的第 2 部分,该系列将指导您配置 IBM ODM 模块、环境和应用程序,以便在 Rule Execution Server 上实现最佳的规则执行性能。第一篇教程 改善 IBM Operational Decision Manager 的性能,第 1 部分:减少规则执行时间 介绍了 IBM ODM 的组件和可缩短规则集执行时间的配置。本教程解决在 Rule Execution Server 上遇到的与资源使用相关的性能问题。
在业务策略变更时,花更少时间来记录和测试。 来自 Bluemix 的 Business Rules 服务 通过保持业务逻辑与应用程序逻辑分析,最大限度地减少了代码更改。免费试用!
除了讨论与特定版本相关的特定行为的时候,本教程适用于 IBM ODM 7.5 及更高版本。教程中所示的配置使用 IBM ODM V8.7,这是本文发表之时的最新版本。请注意,一些配置的默认值在不同版本中不同。请在产品文档中确认您使用的版本的配置。要利用客户修补程序和特性,请确保您已在所使用的版本上安装了最新的修补包。
如果在 z/OS 上使用 IBM ODM,那么除了本系列中建议,还应参阅以下资源:
回页首
在 Rule Execution Server 上运行规则时,以下症状是报告最多的性能问题。
本教程重点介绍解决以下问题的建议:高内存和 CPU 利用率。系列的第 3 部分解决托管的透明决策服务的缓慢响应时间问题。
对于每种场景,性能可能会受规则跟踪和日志记录的影响。减少规则跟踪和日志可能会有所帮助,如第 1 篇教程中的 减少实际规则集执行时间的推荐配置 节中所述。
回页首
组织面临的性能挑战之一是执行规则时内存利用率很高。症状包括高内存使用率和 OutOfMemoryErrors
。
如果遇到高内存利用率,从以下位置收集诊断信息会有所帮助:
rulesetUsageMonitorEnabled
执行单元 (XU) 属性设置为 true
。请参阅 IBM ODM 文档中的 获取执行单元 (XU) 内存使用信息 。 分析堆使用情况,以查明在何处使用了堆,例如在规则集解析或规则集监视期间。
可通过更改规则集设计、服务器配置和应用程序设计来减少规则集执行期间使用的内存,如图 1 所示。
图 1. 减少内存使用的建议
要减少规则集执行期间的内存使用,可应用第 1 篇教程中的规则集设计更改 节中减少规则集解析时间的建议。此外,执行一下规则集设计更改,如图 2 所示。
图 2. 减少内存使用的规则集设计
select
关键字(使用 静态 BAL 规则任务属性 指定), dynamicselect
关键字(使用 动态 BAL 规则任务属性 指定),后跟一个规则域。 使用 dynamicselect
关键字而不选择规则域,可能是永久生成 (PermGen) 空间不足的原因之一,因为然后会为每次执行生成字节码。如果对一个运行 Rule Execution Server 的进程运行 jmap -permstat
命令,可以发现占用 PermGen 空间的不活动类加载器,比如 IlrBinaryClassLoader
和 IlxJITClassLoader
。这些类加载器可在解析规则集时创建,尤其是对于具有 Sequential 和 Fastpath 执行模式的规则任务。类加载器用于将字节码加载到 Java® 虚拟机 (JVM) 中,字节码是在运行时为执行规则任务而生成的。如果使用 dynamicselect
关键字而不选择规则域,可能为规则任务的每次执行生成一个类加载器。
使用 dynamicselect
关键字和一个规则域,可减少 Rule Execution Server 所需要的使用 PermGen 空间的类加载器数量。它也可确保字节码仅为该规则任务生成一次。对这些类加载器的引用会在从 Rule Execution Server 规则集缓存中删除规则集后丢弃,JVM 可以自由地收回该空间。但是,JVM 的实现确定了不活动的类加载器在 PermGen 中保留的时间。请参阅 dW Answers 上的 Rule Execution Server 和 JVM 的 PermGen 空间中的不活动类加载器 。
如果仅部署了一个活动版本,可将 ruleset.maxIdleTime
规则集属性设置为 0
并设置部署策略来更换版本,以便一次只有一个活动的规则集版本(参见 IBM ODM 文档中的版本策略选项)。此值可确保规则集不会从缓存中删除,除了在重新部署(和重新解析)它时。如果部署了多个版本且 ruleset.maxIdleTime=0
,那么即使所有请求都是针对最新版本的,最新版本以前的版本也会无限期地缓存在内存中。因此,在一个规则集的多个版本上使用 ruleset.maxIdleTime=0
,可导致在没有任何针对旧版本的执行请求以后很久,旧版本仍保留在内存中。因此,不推荐使用此方法。在此场景中,可将 ruleset.maxIdleTime
设置为大于 0
的值,以确保规则集版本会在超出最大空闲时间后从缓存中清除,进而释放内存。
如果将 ruleset.maxIdleTime
设置为 >=0,您还应确保 rulesetUsageMonitorEnabled
属性设置为 true
。请参阅 IBM ODM 文档中的 管理规则集的最大空闲时间 。
按照以下指南配置服务器:
可在 IBM ODM 文档中的部署架构 中进一步了解如何选择正确的部署架构。
图 3. 减少内存使用的 XU 连接池配置
执行单元维护着一个连接池。每个连接引用一个一解析的规则集实例,这个实例可在调用时立即执行。如果使用 Java Platform, Enterprise Edition (Java EE),可以通过应用服务器配置连接池大小;或者如果使用 Java SE,可在 ra.xml
文件中配置。
如果遇到内存问题,可减小连接池大小。配置池大小来平衡内存资源限制与规则集执行性能需求。正如第一篇教程 中 “减少规则集解析时间的建议” 下的 “执行单元配置” 节中所讨论的,连接池应足够大,以便满足以下条件:
不对较少使用的规则集调用规则集解析。
要平衡此需求与有限的内存资源,可考虑基于规则集的调用和更新频率来为它们分配不同的连接池,如图 3 所示。可为以下类型的规则集配置不同的连接池:
IlrRulesetUsageInformationMonitorImpl
类使用了大量内存,可考虑将执行单元 rulesetUsageMonitorEnabled
属性设置为 false
,禁用对执行单元的规则集使用数据的监视。这将释放与 IlrRulesetUsageInformationMonitorImpl
类关联的内存。请注意,这么做会禁用对执行单元内存使用情况的监视,以及抑制 ruleset.maxIdleTime
规则集属性的值的效果。 .dsar
文件)时,通过 Rule Designer 会尽可能多创建 .dsar
文件,以便在其中生成字节码。 从 Decision Center 生成的任何 .dsar
文件都不包含字节码,所以必须在运行时生成字节码。将 compiledArchivesCacheProperties
XU 属性设置为 true
,配置已编译的归档文件缓存来限制字节码仅在规则集第一次执行时生成。在后续执行过程中,会从基于文件的缓存中读取生成的字节码。
要释放内存,可通过将 compiledArchivesCacheProperties.maxSize
XU 属性的值调节为小于其默认值 10
,减少缓存中的已编译归档文件的最大数量。
:
-Xms
和 -Xmx
开关指定初始和最大大小,覆盖默认堆大小。 java.lang.OutOfMemoryError:PermGen space
错误,可使用 -XX:MaxPermSize
JVM 开关增加永久生成堆。如果应用程序使用动态代码生成,例如如果使用 JavaServer Pages (JSPs) 或生成的字节码来支持规则集,则应增加 GermGen 堆空间。要确定最优的 MaxPermSize
值,可使用实际的负载设置来对应用程序执行负载测试,包括热部署,并监视堆和 PermGen 的使用。 -verbose:gc
关联解析持续时间与堆清理。相应地调优垃圾收集器和内存大小: -Xms3064M -Xmx3064M -verbose:gc -d64 -XX:MaxPermSize=256m
-Xgcpolicy:gencon
选项帮助最小化任何垃圾收集暂停所花的时间。在 IBM JVM 上, gencongarbage
收集器策略在中小型应用程序上拥有良好的结果。 -Xjit:{ilog/rules/engine/sequential/generated/*}(disableInlining)
能改善性能的 JVM 参数可能类似于下面这个示例:
-Xgcpolicy:gencon -Xmn2048M -Xgcthreads4 -Xcompressedrefs -Xjit:{ilog/rules/engine/sequential/generated/*}(disableInlining) -Xmx4096m -Xms4096m
-Xgcthreads4
开关表示垃圾收集线程的数量,包括应用程序线程,而且默认比 CPU 数量少一个。
在客户端执行以下更改,只要它们适用于您的环境:
OutOfMemoryErrors
。可使用Decision Warehouse 检查输入参数的内容。对于 XML 数据,可使用来自 XML 库的工具来测量 XML 对象的大小。对于大型 XML 对象(XML 解析的成本占整体处理成的很高比例),可执行 XPATH 查询来提取需要的值,然后将该信息传递给规则集。 IlrXmlDefaultDataDriver()
类,可调用 end()
方法来恰当地处置分配的内存。 IlrJ2SESessionFactory
独体对象。例如,保留会议工厂的一个静态引用,或者实现一种独体设计模式来保存会话工厂的共享引用。如果在每次执行时重新创建会话工厂,每次都会重新创建一个 XU 池,而且不支持在客户端之间共享引擎和规则集资源。因此,这会增加内存使用。 回页首
回顾一下,目前为止,本教程讨论了减少内存使用率的建议。同样地,在执行规则时,系统可能具有很高的 CPU 利用率,或许甚至发生 CPU 饥饿。线程转储可能表明大量线程在等待连接。
如果发生高 CPU 利用率,从以下来源收集诊断信息会有所帮助:
trace.log
。要诊断问题,可将跟踪级别设置为 *=info:com.ibm.rules.*=all
以获得最多信息。 高 CPU 利用率可能源于大量的并发请求。分析有多少平法客户端在同时执行规则集,执行频率是多少。另外分析有多少不同的规则集在执行。例如,多个线程可能同时执行规则集解析,这非常消耗资源。
可通过更改规则集设计、服务器配置和应用程序设计来减少 CPU 利用率,图 4 进行了总结。
图 4. 减少 CPU 利用率的建议
如果在 IlrRulesetProvider.getRuleset
方法上看到挂起的线程,可将 ruleset.shareable
属性设置为 false
,以便排除任何与跨多个执行线程共享同一个规则集对象相关的潜在同步或争用问题。但是,此更改可能对内存占用和规则集解析产生重要影响,因为并发执行的线程可能请求规则集的多个已解析和已缓存的表示。
按照以下指南配置服务器:
考虑利用特定于应用服务器的池属性。例如,如果在 WebSphere Application Server 中看到以下错误: J2CA0045E:Connection not available while invoking method createOrWaitForConnection for resource jdbc/resdatasource
,可对连接池设置执行以下更改:
如果适用,依据以下指南来设计您的客户端应用程序:
IlrJ2SESessionFactory
独体对象。例如,保留会议工厂的一个静态引用,或者实现一种独体设计模式来保存会话工厂的共享引用。如果在每次执行时重新创建会话工厂,每次都会重新创建一个 XU 池,而且不支持在客户端之间共享引擎和规则集资源。因此,CPU 使用率会增加。 有关性能改进的更多指南,请参阅以下资源:
回页首
本教程介绍了配置 IBM ODM 和规则和客户端应用程序,以减少规则执行期间的资源使用的推荐实践。可选择最适合您需求的设置,并相应地自定义您的应用程序和环境。本系列的下一篇教程 介绍如何减少托管透明决策服务的响应时间。
整合这些建议之前,请确保您阅读了这个改善 IBM ODM 的性能 系列的第 1 部分。
感谢 Franck Delporte、Alain Robert 和 Pierre Berlandier 对本教程的评审和贡献。另外感谢 IBM ODM 技术解决团队 - 包括 2 级支持、3 级支持和研发团队 - 以及参考文档的作者。