根据消息批处理大小深度控制 BizTalk 中的编排节流和调度

Deeply control orchestration throttling and dispatching in BizTalk based on message batch size

我有一个处理单个消息的 biztalk 编排。这些消息实际上是一批消息。大多数时候,批量大小 n 很小 (<1.000),但偶尔会有非常大的批量 (>50.000)。我们的消息吞吐量也很高。

编排占用系统内存的线性 O(n) 量,具体取决于批处理大小,我通过观察知道单个服务器在用完之前可以并行处理高达 ~250k 的累积批处理大小系统内存,只有 returns OutOfMemoryExceptions。 (这将终止 BizTalk 主机实例,并且业务流程将在另一台主机上启动,最终再次中断,使我们的 BizTalk 组处于中断状态,目前只能通过手动干预恢复)

小批量很常见,大批量很少见,但如果同时有多个批量则有点致命。

我提前知道批量大小,所以我可以告诉 biztalk。但我看不到与节流交互的方法。当节流检测到系统内存不足时,为时已晚。

我是否必须在 biztalk 之上构建自己的排队和调度才能实现我的目标?

我们目前的解决方案是使用值为 8 的信号量,并且每条大消息 n>1000 都需要获得一个信号量槽才能开始处理。前几天我们遇到了一个边缘案例,即使这样也太多了。我们将 8 减少到 4 来解决这个问题,但现在,我们显着影响了一般吞吐量。

欢迎任何想法或提示!

  1. 不要在处理过程中使用 XmlDocument。它会进一步加剧你的记忆问题。在这里肯定会选择 XmlReader。但是,我仍然会尝试将处理移到您的编排之外。即使您可以在从编排调用的 .NET 组件中获得流式处理,您仍然可能以长时间运行并消耗大量内存的编排实例结束,应尽可能避免这种情况。因此...
  2. 避免让业务流程开始时收到那么大的消息。如果您可以将模式标记为信封模式,则可以使用 OOB XmlDisassembler 对消息进行分批处理;如果没有,您可能需要创建一个自定义反汇编程序组件来进行分批处理(请记住 promote/write 将正确的上下文属性添加到来自原始消息的新创建的消息中)。如果你使用一些流媒体技术(参见 https://www.microsoft.com/en-us/download/details.aspx?id=20375) in the pipeline, you can greatly reduce the memory footprint and have much greater control there. Again, use XmlReader to actually parse and debatch the message (it shouldn't be super difficult - look into the ReadToFollowing and ReadSubTree, as in this Splitting large xml files in to sub files without memory contention)。您可能会在编排而不是管道组件中执行此操作,但在管道组件中应该更容易控制内存使用。如果您需要将消息重新关联在一起,您也可以考虑推广诸如批 ID 之类的东西。

  3. 如果你得到一个大批量,你仍然需要限制并发编排的数量;你可以按照 Richard Seroter 的建议 here, which uses multiple convoys that correlate on instance IDs to prevent too many from running at once. Alternatively, you could use ordered delivery on the receive shape (see MSDN) 这样做,这可能是我的首选,因为它需要的工作要少得多,而且不会面临对车队可能出现的僵尸消息的担忧。

基本上:尽量从小处着想,BizTalk 会更快乐。 BizTalk 宁愿在一秒钟内处理 1000 条小消息,也不愿在一分钟内处理一条非常大的消息。