
聚集
聚集是一种功能强大的重要企业服务总线 (ESB) 模式。 入站请求可以映射到多个出站请求。 来自这些请求的响应可以用于丰富对某个服务所作的最终请求,并可以聚集到原始请求的单一响应中。
下面是一些常见场景:
- 在汽车比较保险报价系统中,提交给 ESB 的单一请求导致先对多个保险服务供应商发出查询,然后返回最佳报价。
- 一个假期订票请求到达 ESB,此请求必须先转发到不同的酒店、机票和租车预订系统,然后才能返回组合响应。
- 在商店订购系统中,销售员可以针对多个订单提交请求并分配这些订单。 进入 ESB 的原始消息通过客户标识来标识每个订单的客户。 因此,必须使用每个客户的发货详细信息来丰富订单请求消息,以使分配步骤具有确保成功所需的所有信息。
创建聚集解决方案时,您在处理模式的详细信息之前,必须了解编程模型的多个核心部分:
- “扇出”调解原语
- “扇出”上下文
- “扇入”调解原语
- “服务调用”调解原语
- 聚集块
- 共享上下文
- 特殊注意事项
“扇出”调解原语
“扇出”调解原语通常在聚集开始时使用。 它提供了根据服务消息对象 (SMO) 中重复结构的大小,对调解流进行分支(一次性方式)或多次触发其输出终端(迭代方式)的能力。 例如,如果入站消息包含一个需要转发到两个服务的结构,那么可以在“扇出”调解原语处对该流进行分支。 要多次调用某个服务并且每次使用重复结构中的不同请求进行调用,您可以使用“扇出”调解原语的迭代方式。 您可以从图 1 所示的“扇出”调解原语属性视图中配置这两种方式。图 1. “扇出”调解原语的属性视图
在缺省情况下,此调解原语针对一次性方式进行配置,但您可以通过选择针对 XPath 表达式中的每个元素按钮并指定重复结构在 SMO 中的位置来更改方式。 “扇出”上下文
“扇出”上下文用于存储以迭代方式使用“扇出”时重复元素的当前项。 “扇出”上下文包含一个整数字段,该字段包含重复元素的实例索引以及该实例本身所在的元素。 例如,如果存在名为 order 的元素的重复元素,那么 Fan Out 上下文将如下所示:
<FanOutContext>
<iteration>0</iteration>
<occurrence>
<order>
<id>1234567890</id>
</order>
</occurrence>
</FanOutContext>
“扇入”调解原语
“扇入”调解原语是“扇出”调解原语的伙伴。 “扇出”调解原语用于确定要生成的消息数,而“扇入”调解原语用于确定何时可以认为聚集完成。 “扇入”调解原语始终与同一个流中的“扇出”调解原语配合使用(例如,“扇出/扇入”调解原语配对不能扩展出请求/响应流边界),并且“扇入”调解原语充当用于确定何时离开聚集块的决策点。 “扇入”调解原语在遇到决策点之前接收多条消息,然后在决策点将接收到的最后一条消息传播到输出终端。 “扇入”调解原语只能与“扇出”调解原语配合使用。支持“扇入”调解原语的三类决策点:
- 简单计数:在输入终端处接收到既定数目的消息时触发输出终端。 但是,“扇出”调解原语可能会发出更多消息, 其原因在于,有可能多次到达“扇入”调解原语计数决策点,从而导致多次触发输出终端。
- XPath 决策:如果对入局消息进行的 XPath 表达式求值的结果为 true,那么触发输出终端。 输出终端有可能触发多次。
- 迭代:“扇入”调解原语等待接收由相应“扇出”调解原语生成的所有消息。 重复元素中的所有实例均已处理完毕。
图 2. “扇入”调解原语的属性视图
“扇入”调解原语有两个输入终端(in 和 stop)、 两个输出终端(out 和 incomplete)以及一个失败终端 (fail)。 您对输入终端进行连接以接受消息,并对其他终端进行连接以传播消息。
在到达决策点之前,in 终端将一直接受消息。 到达决策点时, 将会触发 out 终端。 虽然在到达决策点时触发了 out 终端,但在某些情况下 in 终端仍可以接受输入消息。 例如,如果到达了计数值,那么将会触发 out 终端。 但是,如果“扇出”调解原语仍在发送消息,那么“扇入”调解原语仍可以接收消息。
您可以通过将前面的调解原语连接到“扇入”stop 来停止“扇入”操作。 stop 终端将导致触发 incomplete 输出终端,这将阻止相关联的“扇出”调解原语再发送任何消息。 如果出现超时,那么也会触发 incomplete 输出终端。 表 1 进一步描述了终端行为。
“服务调用”调解原语
“服务调用”调解原语在“扇出”与“扇入”调解原语之间使用,并用于调用所需的服务。 服务调用一章对“服务调用”调解原语作了讨论。聚集块
您创建聚集解决方案时,“扇出”调解原语声明聚集开始,“扇入”调解原语将聚集的结束符号化。 这两个调解原语之间的逻辑可以被视为重复块(如果将“扇出”配置为处于迭代方式)或者分支(如果将“扇出”配置为处于一次性方式),如图 3、、、
和 所示。
图 3. 聚集块的示例
共享上下文
在 SMO 中有 3 个由用户定义的数据存储上下文:- 存储在瞬态上下文中的数据在请求流或响应流中可用。
- 存储在关联上下文中的数据在请求流和响应流中都可用。
- 存储在共享上下文中的数据在聚集块的所有分支和执行中都可用。
聚集调解编程模型特殊注意事项
在使用聚集功能时,请考虑下列事项:- 共享上下文是 SMO 的组成部分,它设计为在聚集块内使用是因为放入其中的数据在所有流分支中都可用。 共享上下文结构的设计是确保聚集设计成功的关键。 其目标为,将来自每个服务调用的响应放入一个结构,然后在聚集块之后将该结构转换为单一响应消息。
- 共享上下文跨 SMO 共享,并且在聚集块外部应该被视为处于只读状态。
- 在开发时,难以确定要从“扇入”调解原语输出终端中发出的 SMO 主体类型。 在“扇入”调解原语之后的调解原语应该用于根据共享上下文中的信息生成新消息体。
- 如果一条消息到达“扇出”调解原语,那么将触发“扇入”调解原语的一个或多个输出终端(例如,假定由于运行“失败”调解原语导致聚集块中未发生 ServiceRuntimeException),即使“扇入”调解原语未接收到消息也是如此。 表 1 突出描述了此行为。
“扇入”调解原语所处的方式 | 消息到达“扇入”调解原语 | 触发的输出终端 | “扇入”调解原语的 SMO |
---|---|---|---|
迭代 | No | 完成 | 消息体为空;SMO 头和上下文与在“扇出”处接收到的消息相同 |
迭代 | 是(in 终端) | 完成 | 在“扇入”调解原语输入终端接收的上一条消息 |
迭代 | 是(stop 终端) | 未完成 | 在“扇入”调解原语输入终端接收的上一条消息 |
简单计数/XPath | 否 | 未完成 | 消息体为空;SMO 头和上下文与在“扇出”处接收到的消息相同 |
简单计数/XPath | 是(in 终端) | 未完成/完成 * | 在“扇入”调解原语输入终端接收的上一条消息 |
简单计数/XPath | 是(stop 终端) | 未完成 | 在“扇入”调解原语输入终端接收的上一条消息 |
迭代/简单计数/XPath | 是,超时值已到期,并且决策类型不完整 | 未完成 | 在“扇入”调解原语输入终端接收的上一条消息 |
迭代/简单计数/XPath | 是,超时值已到期,并且决策类型完整 | 完成 | 在“扇入”调解原语输入终端接收的上一条消息 |