线程技术

消息处理节点和解析器必须在多实例、多线程环境中工作。可以有许多节点对象或解析器对象,每个多具有许多语法元素,并可以有许多 在这些对象上执行方法的线程。消息代理设计确保消息对象和它拥有的任何对象仅由线程使用,该线程通过消息流接收和处理消息。

由服务消息流(在此定义节点)的所有线程共享和使用消息流处理节点的实例。对于解析器,仅由单个消息流线程使用解析器的实例。

用户定义的扩展名应该遵循此模型,并且应该避免使用需要信标来序列化跨越线程访问的全局数据或资源。这样的串行化会导致性能瓶颈。

用户定义的扩展实施函数必须是可重入的,并且它们调用的任何函数必须同样是可重入的。所有用户定义的扩展实用程序函数都似乎完全可重入的。

尽管用户定义的扩展可以衍生其他线程(如果必需),对于同一个线程将控制权返回到有关实施函数的完 成的代理这是必不可少的。如果此操作失败则将损害代理的完整性并会产生不可预测的结果。

执行模型

当初始化执行组时,使相应的 lil 可以用于运行时。执行组运行时进程启动,并衍生专用的配置线程。在消息流执行环境中,消息流是线程安全的。您可以在许多 OS 线程上并发地运行消息流,而不必考虑序列化问题。您实现的任何用户定义的节点都不应该损害此线程技术模型。注意以下要点:
  • 发送到消息流的输入消息仅通过接收它的线程处理。在消息处理期间不发生线程或上下文切换
  • 由消息流访问的数据结构仅对单个线程可视,并且这些数据结构仅对正在处理的消息生命期存在。
  • 消息流的单个实例在所有消息流线程池中的线程之间共享。这与消息流节点的行为相关,在节点中它没有状态。
  • 执行组的内存需求不会受在多个 OS 线程上运行消息流的过度影响。

线程技术模型

以下消息流示例会帮助您理解在设计和实现用户定义的节点时应该注意的一些线程技术注意事项。它设想了一个用户定义的输入节点的示例。

消息流可以配置为在一组线程上运行。这由消息流中的一些输入节点,以及消息流的附加实例属性的值确定。这两个元素确定消息流可以使用的线程池的最大容量。因此,如果消息流具有指示单个线程执行的特殊处 理需求,则您需要确保就是这种情况。

输入节点处理的事件的通常顺序与此类似:
  1. 发生输入节点构造
  2. 需要来自线程池的线程
  3. 在节点的运行方法中启动已分配的线程
  4. 已提交配置(或重新配置)
  5. 在线程上下文上执行初始化处理
  6. 该线程连接到代理的队列管理器
  7. 创建了消息组和缓冲区对象
  8. 将输入队列的队列打开请求发送到队列管理器。此队列在线程的生命期期间保持打开。
  9. 输入节点输入消息处理循环
  10. 当接收到消息时,数据缓冲区包含头和消息体。
  11. 创建消息对象并附加到线程的组
  12. 如果指定了多个线程,则激活线程分派
  13. 向下游传播消息数据。
您应该注意下列事项:
  • 输入节点会实现选择消息流线程技术模型。
  • 您的输入节点将总是至少有一个线程在从它的输入源读或积极处理它接收的消息。如果消息流有多个输入节点,则任何其他线程实例对任何输入节点可用,由该输入节点的分派策略确定。
线程可以被需求或请求。当部署您的消息流时,输入节点需要初始线程。尽管消息流有一个与其关联的线程池,但它是对分派策略负责的输入节点。这意味着它总是需要确保它本身的一个实例正在线程上运行。因为 additionalInstances 属性的缺省值是 0,线程的任何进一步请求都会失败,如果您已定义多个输入节点的话。这意味着消息流消耗多个您期望的线程是可能的。同样,这也意味着如果您已定义多个输入节点,则输入节点之一可能缺少线程。

使用 additionalInstances 属性来允许代理启动其他单独线程中的消息流的副本是防止输入队列成为瓶颈的最有效的方法。然而,创建单独线程允许消息队列的消息并行处理,因此您应该仅当处理的命令消息不重要的时候才使用。

线程作为输入节点构建和操作的结果创建。 线程在线程池中保持活动或空闲,且空闲线程保持在池中,直到输入节点分派它们,或关闭代理。

下图描述消息流中的线程分配。

消息流中的线程分配


请参阅随附的文本获取图表中元素的说明

最初,Thread 1 被需求(A),并等待消息。当消息到达(B),Thread 1 传播消息,并分派 Thread 2。Thread 2 立即接收消息(C),并传播和分派等待消息(D)的 Thread 3。Thread 1 完成(E),并返回到线程池。然后 Thread 3 接收消息(F),分派 Thread 1,并传播消息。现在 Thread 1 等待消息以到达队列(G)。

应当注意标记为 H 的点。在消息流的这个实例,Thread 1 获取消息,但因为所有其他线程在那时是活动的,所以它无法分派。则消息被传播。

在已传播此消息之后,Thread 2 完成(I),从队列接收新消息,并传播此新消息。然后 Thread 3 完成(J),并返回到池。然后 Thread 2 也完成(K)。因为它不分派,当 Thread 1 完成(L)时,它无法返回到线程池,即使队列上没有消息,相反它等待消息以到达队列。

注意以下关于 WebSphere Message Broker 中线程行为的要点:
  • 仅当工作负载需要时才创建线程。这意味着执行组进程可以使用比它已配置的更少的线程。
  • 除非所有可用的线程在消息流中积极地处理,否则有一个线程总是在读输入队列。
  • 如果工作负载增加,同一消息流中的其他输入节点可以获取已返回到线程池的线程。
如果线程获取消息,但所有其他线程在那时是活动的,则它无法分派。则消息被传播。当此线程完成时,因为它没有分派,所以它无法返回到线程池,即使队列上没有消息。
相关参考
cniDispatchThread
声明 | 商标 | 下载 | 书库 | 支持 | 反馈
Copyright IBM Corporation 1999, 2006 最后一次更新时间:2006/08/14
as01460_