我对LMAX Disruptor有一些经验,我真的很想使用disruptor实现自定义actor邮箱。
有没有指导方针?它甚至可能吗? Akka的演员邮箱有哪些局限性?
答案 0 :(得分:3)
正如它所说here你只需要实现一些方法 - 当然你应该使用指向环形缓冲区的指针直接写/读消息。你还应该记住:
破坏者通常预先分配大量内存,因此每个玩家使用一个破坏者是个坏主意,你可以使用一个路由器actor(里面有disruptor)和BalancingPool
。
如果你想要不同的消息类型消费,单独的消费者进行日记,修复等等 - 你应该将不同的RingBufferPointer(类似smthng)实例作为参数传递给你的邮箱(具有相同的日记记录起始值,不同的消息类型的不同起始值),但仍然使用一个Disruptor。所以不同的邮箱会引用一个破坏者。
您将在消息创建,解压缩等方面失去低级别控制权,因此默认情况下不进行批量分配。
您还可以使用响铃中的历史记录来恢复失败的演员的状态(在preRestart
或主管中)。
LMAX说:
它以与传统方法不同的方式工作,所以你 使用它与你可能习惯的有点不同。例如, 将模式应用于您的系统并不像更换所有模式那么简单 你的队列与魔法环缓冲区。我们有代码示例 引导您,越来越多的博客和文章给出了概述 它是如何工作的,技术论文详细说明了你的情况 期待,性能测试给出了如何使用的例子 干扰器 http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html
here是一个简短的队列/干扰器/演员比较
在伪scala代码中,它将类似于:
object MyUnboundedMailbox {
val buffer = new RingBuffer()
class MyMessageQueue(val startPointer: Pointer, readerPointer: Pointer, writerPointer: Pointer) extends MessageQueue {
// these should be implemented; queue used as example
def enqueue(receiver: ActorRef, handle: Envelope): Unit = {
writerPointer.allocate(() => handle) //allocate one element and set, if you want different message types - you should allocate big amount of data before and block when it ends (to not interfere with another messages), so it has to be bounded queue then
}
def dequeue(): Envelope = readerPointer.poll()
def numberOfMessages: Int = writerPointer - readerPointer //should be synchronized
def hasMessages: Boolean = readerPointer == writerPointer //should be synchronized
def cleanUp(owner: ActorRef, deadLetters: MessageQueue) { }
}
trait MyUnboundedMessageQueueSemantics
}
class MyUnboundedMailbox(settings: ActorSystem.Settings, config: Config) extends MailboxType
with ProducesMessageQueue[MyUnboundedMailbox.MyMessageQueue] {
import MyUnboundedMailbox._
final override def create(owner: Option[ActorRef],
system: Option[ActorSystem]): MessageQueue = {
val pointer = ring.newPointer
val read = pointer.copy
val write = pointer.copy
new MyMessageQueue(pointer, read, write)
}
// you may use another strategy here based on owner (you can access name and path here),
// so for example may allocate same pointers for same prefixes in the name or path
}
您可以使用未更改的MyMessageQueue.startPointer在故障恢复期间访问消息日志(您也可以查看akka' s Event Sourcing进行类比)。
使用UnboundedQueue方法并不能保证此处的邮件传递,因为如果响铃结束,可能会使用新版本覆盖旧的未传递邮件,因此您可能需要BoundedQueue,如here