应该如何使用Disruptor(Disruptor Pattern)来构建现实世界的消息系统?

问题描述 投票:0回答:4

由于 RingBuffer 预先分配给定类型的对象,如何使用单个环形缓冲区来处理各种不同类型的消息?

您无法创建新的对象实例来插入到ringBuffer中,这将违背预先分配的目的。

因此,您可以在异步消息传递模式中拥有 3 条消息:

  1. 新订单请求
  2. 新订单已创建
  3. 新订单被拒绝

所以我的问题是如何在现实世界的消息系统中使用 Disruptor 模式?

谢谢

链接: http://code.google.com/p/disruptor-net/wiki/CodeExamples

http://code.google.com/p/disruptor-net

http://code.google.com/p/disruptor

disruptor-pattern
4个回答
34
投票

一种方法(我们最常见的模式)是以编组形式存储消息,即作为字节数组。对于传入的请求,例如修复消息(二进制消息)会快速从网络中拉出并放置在环形缓冲区中。不同类型消息的解组和分派由该环形缓冲区上的事件处理器(消费者)处理。对于出站请求,消息被序列化到预先分配的字节数组中,该数组形成环形缓冲区中的条目。

如果您使用某些固定大小的字节数组作为预分配条目,则需要一些额外的逻辑来处理较大消息的溢出。 IE。选择一个合理的默认大小,如果超过则分配一个更大的临时数组。然后,当该条目被重用或消耗(取决于您的用例)时丢弃它,恢复到原始预分配的字节数组。

如果您对不同的消息类型有不同的消费者,您可以通过了解携带类型信息的字节数组的偏移量或通过在条目上传递鉴别器值来快速确定您的消费者是否对特定消息感兴趣。

此外,没有禁止创建对象实例和传递引用的规则(我们也在几个地方这样做)。您确实失去了对象预分配的好处,但是破坏者的设计目标之一是允许用户选择最合适的存储形式。


6
投票

有一个名为 Javolution (http://javolution.org/) 的库,它允许您将对象定义为具有固定长度字段(如 string[40] 等)的结构,这些字段内部依赖于字节缓冲区而不是可变大小的对象。允许使用固定大小的对象初始化令牌环,从而(希望)使用连续的内存块,使缓存能够更有效地工作。

我们使用它来传递事件/消息,并使用标准字符串等来实现我们的业务逻辑。


0
投票

返回对象池。

以下是一个假设。

如果您有 3 种类型的消息(A、B、C),您可以创建 3 个预先分配的数组。这将创建 3 个内存区域 A、B、C。

并不是只有一个缓存行,而是有很多个,而且它们不必是连续的。一些缓存行将引用区域 A、其他 B 和其他 C 中的某些内容。

因此,环形缓冲区条目可以有 1 个对 A、B 和 C 的共同祖先或接口的引用。

问题是选择池中的实例;最简单的方法是使数组长度与环形缓冲区长度相同。这意味着大量浪费的池化对象,因为在任何条目中仅使用了 3 个对象中的一个,例如:环形缓冲区条目 1234 可能正在使用消息 B[1234],但 A[1234] 和 C[1234] 未使用且不可用任何人。

您还可以创建一个超级条目,其中内联所有 3 个 A+B+C 实例,并用某些字节或枚举指示类型。同样浪费内存大小,但由于条目过多,看起来更糟糕。例如,仅处理 C 消息的读取器将具有较少的缓存局部性。

我希望这个假设没有太大错误。


0
投票

使用Disruptor的低延迟、高可用、高并发交易服务技术方案

https://www.devean.cn/cn/blog/2024/qptrade/

© www.soinside.com 2019 - 2024. All rights reserved.