简介: ?本文以多个客户企业的经验为基础,给出了使用 WebSphere Message Broker 来开发和部署可靠且可扩展的 ESB 解决方案的一些最佳实践。
?
引言
IBM? WebSphere? Message Broker(以下称为 Message Broker)可以作为企业服务总线使用,提供用于各种协议的通用连接以及为使用结构化和非结构化数据的应用程序提供数据转换功能。
消息处理性能取决于很多因素,包括硬件能力、软件配置、消息流和消息格式设计及实现,以及消息流实例的数量。本文将描述为众多客户带来了性能和消息流服务可用性改善的实现和部署最佳实践。虽然本文并不讨论关联的 WebSphere MQ 和数据库实现的最佳实践,但会从消息代理应用程序的角度对其有所涉及。最佳实践并不是万能的,在某些情况下,此处所述的最佳实践需要进行修改,以满足体系结构灵活性和适应客户的具体需求和能力。
最佳实践领域
消息流
- 通常,为了将配置信息同业务逻辑分离,客户会将配置信息外部化到文件或数据库中。此技术可能会降低性能,因为读取配置或参数文件是在创建节点的第一个实例时或处理第一个消息时的一次性活动,而不会对每个消息都进行循环检查。由于 Message Broker 更多的是面向 CPU 而不是 I/O,通常最好尽可能避免涉及文件或数据库的 I/O 操作。
- 尽可能使用部分解析方法,除非业务需要消息的完整解析。在消息流的最后,如果有输出节点(如 MQOutput),则将出现消息、转换为位流),会解析完整的消息。此 Message Broker 功能能帮助改进性能,因此尽可能对其加以利用。
- 处理成本与消息树的大小之间存在直接的正比关系。因此,消息树大小和设计在处理成本中扮演着重要的角色。例如,将所有这些可能使用的字段都放置在决策中,以在消息的开始位置路由消息。由于对消息树进行部分解析时并不会完全解析,因此消息将路由到下一个节点。如果消息在 Header 中包含用户可维护的数据文件夹(如 MQRFH2 usr 文件夹),则建议最好在其中存储决策路由元素。
- 尽可能减少消息流中的节点数量。还要尝试减少消息树副本或创建新消息树。消息树占用了大量的空间,特别是在包含大量元素的情况下更是如此。仅在必要时使用计算节点(提供修改树的能力)之类的节点,以避免出现消息树副本。这不仅从内存利用率方面提高了效率,而且还提高了处理速度。
- 避免使用重置内容描述符 (Reset Content Descriptor) 节点。RCD 节点旨在用于更改实际解析完整消息树的消息域。此活动的内存和 CPU 使用量都较大。
- 可以使用 IF 语句、“CREATE with PARSE”语句和 ESQL ASBITSTREAM 的逻辑组合来消除 RCD 节点和多个计算/筛选器节点。
- 不要在生产环境中使用跟踪节点。使用 ${Root} 表达式的操作开销非常大,因为这会导致进行完整消息树解析。如果目的地不处于活动状态,就会发生这样的情况。
- 在可能的情况下,请尽量使用用户退出,并恰当地重定向审核/日志记录信息。使用退出功能能够获得灵活性,可在消息处理期间动态地激活和取消激活。
- 将中介结果保存在消息树中,以避免在后续节点中进行重新计算。如果消息在 Header 中包含用户可维护的数据文件夹(如 MQRFH2 usr 文件夹),则将中间结果存储在其中,以供后续节点使用。
- 当必须将消息写入到多个目的地时,建议使用目的地列表,而不要采用使用多个节点的方法。
- 使用 XMLT 节点时,请注意消息树将首先被序列化,然后再被发送到转换引擎。加载了样式表并执行转换之后,节点要将结果重新解析为消息树。另外,Message Broker V6 中 XMLT 节点的输出始终为 BLOB 格式,因此如果消息处理必须在消息流中进一步作为 XML 消息处理,则必须使用 RCD 节点。因此,将通过多次使用 XMLT 节点解析整个消息树。如果要转换的消息树很大,此操作开销将非常大。同时,如果 ESQL 与更好的逻辑一起使用,则处理成本将大幅度减少,因为不需要解析完整的消息树,所得到的好处更多。
- 如果要使用 XMLT 节点,则请尽可能使用样式表缓存。
- 仅将消息流用于执行转换、翻译、协议转换、消息充实和路由等中介活动。消息流应该是中介活动中的无状态引擎。
- 确保在消息处理期间输入节点的转换模式设置为“NO”,输出节点设置为“Automatic”。只有当处理在转换模式下完成时才应该使用其他设置。
- 始终为消息流配备异常处理机制,而不要依赖缺省代理异常处理程序。缺省异常处理程序可以在单个被破坏的消息处理失败时阻塞消息使用。
- 使用子流,以便在多个消息流重用代码,尤其在使用或考虑多个协议时。
- 在筛选器或数据库节点中,不可能修改消息树,在这种情况下,请在节点中使用环境 (Environment) 树来修改消息树内容并将其复制到后续节点中。
- 如果有数据操作节点,则请提升数据源名称属性,因为此属性在各个环境(开发、测试、生产等)中可能并不相同。提升此属性可帮助在各个环境中部署时在流级别(而不是每个节点的级别)对其进行更改。这也适用于其他节点属性(如 XMLT 节点的样式表名称)。
- 回顾所有 Java 节点,并确保每个 MbMessage 对象上都会调用 clearMessage()(特别是在 finally 块中)。MbMessage 对象用于创建输出消息树、环境树、本地环境树、异常列表树等等。因此,任何时候创建消息树时,都要将其清除出 try - finally 块。
- 强烈建议减少复杂性较高的节点,不要使用大量节点而导致处理逻辑分散。
- 每个消息流就是一个线程。为了获得有效的处理完整性,最好不要在消息流节点中产生其他线程。如果出现了业务需求,则应该由节点本身维护所有线程,并在节点删除时释放,以确保在消息处理期间不会出现线程阻塞。
ESQL
- 尽可能避免使用本地环境 (Local Environment) 树,而应将环境树用于存储中间结果。对于消息流实例的所有节点而言,只存在环境树的一个副本,消息树将被复制到所传播到的每个节点。
- 在 ESQL 编码期间使用动态引用来提高消息树导航的效率。
- 在 ESQL 中使用 PASSTHRU 语句时,请使用参数标记“?”。这非常重要,因为通过这样可以重用 Dynamic SQL 语句。
- 不要在循环中将相同的函数调用用于相同的用途。例如:在 ESQL WHILE 循环中调用 CARDINALITY 函数开销比较大。
- 如果需要发送相同输入消息的多个输出消息,请在 ESQL 中使用 PROPAGATE 函数。对于完成的每次消息传播,这将帮助回收输出消息树的存储。这样可能会降低消息流的内存利用率。另外,请避免使用硬连接的流循环。
- 使用 ROW 和 LIST 构造函数创建字段列表。另外,最好在进行声明时进行变量初始化。这样可以尽可能减少 ESQL 语句的数量。通过这种做法,可以提高性能,并减少要创建和解析的内部内存对象的数量。
- ESQL 字符串操作处理器开销较大。请尽可能减少使用此类操作。
发布/订阅
- 使用发布/订阅时,每个主题的订阅者数量将影响消息吞吐量,因为这将决定主题上的每个发布操作将必须写入多少个输出消息。消息将在单个工作单元内写入,因此在使用持久消息时需要调整代理队列管理器日志。
- 使用发布节点可能会增加代理数据库的使用,特别是涉及的发布是代理存储在代理数据库的保留发布时更是如此。因此,要明智地确定发布是否必须为保留发布。
- 每个订阅注册和重新注册的详细信息存储在代理数据库表中。如果应用程序动态订阅或取消订阅的级别太高,则代理数据库操作的级别也将更高。所有 I/O 和 DB 操作的开销都比较大。因此,设计解决方案时要尽可能减少这些操作,或优化数据库来获得高性能。
- 设计发布/订阅模型时,请考虑通过基于主题的路由方式进行路由。通过使用基于内容的路由,可以很方便地针对消息的内容评估 SQL 表达式,从而决定订阅者是否真的需要获得消息。这可以帮助减少从代理发送到订阅者的消息数量。采用基于主题的路由,订阅者将获得所注册主题上的所有消息。订阅者可能不需要所有消息,可以根据内容将消息丢弃。因此,基于内容的路由能帮助订阅者从中获得真正需要的大部分消息。
从 Message Broker 的角度确定的 WebSphere MQ 最佳实践
- 消息流设计为依赖于 CPU 时,Message Broker 处理性能会更好(前提是 CPU 处理能力足够)。对于 WebSphere MQ 上的持久消息,由于 WebSphere MQ 要对其加以记录,因此变成了依赖于 I/O。因此,如果不存在这种业务需求,就不要将消息变成持久消息。另外,要对每个非持久消息设置到期信息。一旦缓冲区用完,即使是处理非持久消息,WebSphere MQ 也会进行 I/O 操作,因此设置消息的到期信息,可避免代理或应用程序不执行处理或消息使用时队列被占满。
- 在 WebSphere MQ 上使用持久消息时,请提高缓冲区大小和队列管理器日志的日志范围大小。另外,请考虑将低延迟磁盘用于存储日志,如使用具有非易失性缓存的磁盘。这样可以极大地提高持久消息的处理速率。
- 如果无法避免 WebSphere MQ I/O,则请尽可能尝试减少此类操作。例如:
- 保持较高的消息处理速率,无论消息类型如何,都尽量减少队列上的消息的数量。可以通过使用多个执行组和多个消息流实例来实现此目标。
- 避免消息到达速率和处理速率之间存在较大的差异。按照上面的建议调整消息流和配置。
- 使用大缓冲区配合高速磁盘进行队列管理器日志记录。
- 将 Message Broker 作为所有受支持的平台上的受信任应用程序使用。这可以帮助减少应用程序(代理)与队列管理器的通信成本。
从 Message Broker 的角度确定的数据库最佳实践
- I/O 操作和数据库操作的开销都很大。尽可能减少解决方案中此类操作的数量。尽可能构建缓存。此决策是完全由业务场景驱动的。也不建议过度构建缓存。
- 解决方案要执行数据库操作时,需要遵循多个与数据库应用程序相关的最佳实践。接下来的几个建议是从使用 DB2 作为数据库的 Message Broker
应用程序的角度提出的,但也适用于大多数其他数据库。
- 调整应用程序堆大小 (APPLHEAPSZ) 和应用程序控制堆大小 (APP_CTL_HEAP_SZ)。由于这些值取决于业务条件和解决方案实现,因此不可能建议固定值。为了确定值,请向数据库发出最大的消息事务(根据业务需求),并监视堆大小。
- 如果应用程序能处理 BLOB、CLOB 和 VarCahr 之类的大型对象,则请调整缓冲区池大小(因为这些对象是通过使用数据库的内存区域访问的)。
- 确保 locklist 和 maxlocks 足够大,或者通过更为频繁地发出 commit 语句减小工作单元。
- 尽可能使用索引来减少消息流实例和应用程序之间的争用。
- 当消息流仅从表读取数据时,请考虑使用表的只读视图。这样可减少数据库管理器中的锁定量,从而减少线程的处理成本。
- 如果数据库操作不可避免,则至少通过以下方式减少其数量:
- 将数据库放在 Message Broker 所驻留系统的本地
- 设置大缓冲区
- 为数据和日志使用高速磁盘。
- 使用 SELECT 语句时,请高效地使用 WHERE 子句来尽可能减少来自数据库的数据量。
- 在可能的情况下,请使用存储过程,因为存储过程已经进行了编译并存储在数据库中。这可提高检索数据的速度。
- 可能时,请避免使用复杂联接,因为复杂联接的处理时间消耗比较大。
配置
- 如果存在多个 Message Broker 组件(不在相同计算机上),请对大型部署中的每个组件使用独立的用户 ID。这样做可保证安全性,并方便进行维护。
- 不要提供对组件服务 ID 的直接登录访问。向可用于替换服务 ID 来执行操作的用户 ID 授予权限。这样可帮助保护组件。
- 不要向用户公开组件服务 ID。用户可以使用“runas”命令利用服务 ID 启动工具集,能够获得组件上的完整权限,因为服务 ID 将缺省获得 ACLE 中的完全拓扑级别权限。
- 使用访问控制列表 (Access Control List) 定义组件级别的操作权限。
- 一旦完成了全面的设置,请减少使用工具集进行管理操作。请使用配置代理管理器 API 执行工具之类的解决方案,或使用本地计算机上的命令。出于安全考虑,请确保不能从远程计算机执行管理活动。为此,可以将配置管理器队列管理器值的 SYSTEM.BKR.CONFIG 通道的 MCA 通道用户 ID 设置为无效的用户 ID 值。这样可确保不能从工具集执行任何进一步的管理操作。
- 不要在“mqsiprofile”中设置环境配置相关信息,而要在用户配置文件中进行设置。在维护活动(如 Fix Pack 更新)期间,这些文件将被覆盖,之前的设置将丢失。
- 根据基于预期负载和可用系统资源的公司策略将 ulimit 设置为相应的值。这也适用于非 Windows 计算机。
- 根据性能测试,得出进程大小。根据需要提高执行组 (DataFlowEngine) 数据分段大小(仅限于 AIX)。如果使用 32 位执行组处理环境中的复杂且数目众多的消息流,1 GB 的缺省值可能不够。
- 从内存的角度而言,请使用 64 位进程(执行组),而不要采用 32 位进程。
- 如果在 Message Broker 解决方案中大量使用了 Java,则请执行多个性能测试来确定 JVM 最大堆大小。应该注意的是,JVM 堆大小是从 DataFlowEngine(执行组)进程分配的。因此,绝不要将进程堆大小值和 JVM 最大堆大小值设置为相同的数字。
- 请使用脚本或相应的 Message Broker 命令执行所有部署活动。设置环境变量 MQSI_SHOW_DEPLOY=1,以在操作系统用户日志中查看详细的部署操作进展情况。mqsilist <brokername> 之类的查询操作也是部署消息,因此也会在用户日志中看到相应的部署信息。
- 始终保留一个与生产环境一致的环境,采用相同级别的配置。如果必须首先执行任何维护工作,请首先在克隆环境上执行,并确保不会对您的系统造成影响。然后再在生产环境中执行此操作。
- 严格地定义命名约定和代码编写标准。确保所有开发人员和管理员都相应地予以了遵从。
- 为所有 Message Broker 构件配备源代码控制机制,并使用部署脚本(ant 或 shell 脚本),以便能方便地进行维护。
- 不要跨组件(代理、用户名服务器、配置管理器)共享相同的队列管理器,特别在生产环境中更是如此。
- 请使用额外的实例机制来提高在执行组中运行的消息流副本数量,而不要为众多执行组中的每个都分配一个消息流副本。
- 请始终维护相应的文档来跟踪生产环境中的所有更改。有时候,即使是很小的更改也可能会导致灾难性的结果。如果记录了各个活动,就很容易进行调试和快速恢复环境。
- 始终在域级别执行备份和恢复。在域级别备份期间,不应该存在任何未完成的部署,而且在备份完成前不应该执行任何部署。
- 在对域或系统环境执行任何更改(Fix Pack 升级之类的常规维护)前,请始终进行备份,这样可以帮助在更新后发现故障时方便地进行恢复。
- 配备测试和维护备份与恢复战略的策略,特别是要充分考虑灾难恢复方案。
结束语
本文介绍了一些 WebSphere Message Broker 最佳实践。虽然使用这些最佳实践应该能提高消息处理性能,但性能还取决于其他各种因素,如有效地调整任何依赖 WebSphere MQ 和数据库实例、良好的解决方案设计以及配备了高性能 CPU 和足够内存的计算机。
?
原文:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/0809_kudikala/0809_kudikala.html