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

时间:2011-08-03 21:12:59

标签: disruptor-pattern

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

您无法创建要插入ringBuffer的新对象实例,这会破坏预先分配的目的。

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

  1. NewOrderRequest
  2. NewOrderCreated
  3. NewOrderRejected
  4. 所以我的问题是你是如何将Disruptor模式用于实际的消息系统的呢?

    由于

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

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

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

3 个答案:

答案 0 :(得分:32)

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

如果使用某个固定大小的字节数组作为预分配条目,则需要一些额外的逻辑来处理较大消息的溢出。即选择合理的默认大小,如果超过,则分配一个更大的临时数组。然后在重用或使用该条目时(根据您的使用情况)将其丢弃,并恢复为原始的预分配字节数组。

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

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:0)

返回对象池。

以下是一个假设。

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

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

因此,环形缓冲区条目可以具有对A& A的共同祖先或接口的1个引用。 B&下进行。

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

您还可以在内联所有3个A + B + C实例的情况下创建一个超级条目,并使用某个字节或枚举指示该类型。就像内存大小一样浪费,但由于条目的肥胖看起来有点糟糕。例如,仅处理C消息的阅读器将具有较少的缓存局部性。

我希望我对这个假设没有错。