簡體   English   中英

如何使用disruptor實現自定義actor郵箱?

[英]How to implement custom actor mailbox using disruptor?

我有一些LMAX Disruptor的經驗,我真的想用disruptor實現一個自定義actor郵箱。

有沒有指導方針? 它甚至可能嗎? Akka的演員郵箱有哪些限制?

正如它在這里所說你只需要實現一些方法 - 當然你應該使用指向環形緩沖區的指針直接寫/讀消息。 你還應該記住:

  • 破壞者通常預先分配大量內存,因此每個actor使用一個破壞者是個壞主意,你可以使用一個路由器actor(內部有disruptor)和BalancingPool

  • 如果你想要不同的消息類型消費,單獨的消費者進行日記,修復等 - 你應該將不同的RingBufferPointer(類似smthng)實例作為參數傳遞給你的郵箱(具有相同的日記起始值,不同的起始值為不同的消息類型),但仍然使用一個Disruptor。 所以不同的郵箱會引用一個破壞者。

  • 你將失去對消息創建,提取等的低級控制,因此默認情況下不進行批量分配。

  • 你也可以使用ring中的歷史來恢復失敗的actor的狀態(在preRestart或supervisor中)。

LMAX說的是什么:

它以與傳統方法不同的方式工作,因此您使用它的方式與您習慣的方法略有不同。 例如,將模式應用於您的系統並不像使用魔術環緩沖區替換所有隊列那么簡單。 我們有代碼示例來指導您,越來越多的博客和文章概述了它的工作原理,技術論文按照您的預期進行了詳細介紹,性能測試給出了如何使用Disruptor的示例http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html

這里有一個簡短的Queues / Disruptors / Actors比較

在偽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的Event Sourcing進行類比)。

使用UnboundedQueue方法並不保證此處的消息傳遞,因為如果響鈴“結束”,可能會使用新版本覆蓋舊的未傳遞消息,因此您可能需要BoundedQueue,就像這里一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM