Akka 访问actor邮箱的邮件

Akka 访问actor邮箱的邮件,akka,Akka,我想阅读ShardRegions邮箱中的邮件。在以前的akka版本中,我们可以使用以下代码仅获取邮箱的大小: getContext().getMailboxSize(); 有没有办法获取邮箱中的邮件类型?以下是解决方案 为碎片区域定义包装器邮箱,如下所示: class UnboundedMailboxWrapper extends MailboxType with ProducesMessageQueue[UnboundedMailboxWrapper.MessageQueue] { de

我想阅读ShardRegions邮箱中的邮件。在以前的akka版本中,我们可以使用以下代码仅获取邮箱的大小:

getContext().getMailboxSize();
有没有办法获取邮箱中的邮件类型?

以下是解决方案

为碎片区域定义包装器邮箱,如下所示:

class UnboundedMailboxWrapper extends MailboxType with ProducesMessageQueue[UnboundedMailboxWrapper.MessageQueue] {
  def this(settings: ActorSystem.Settings, config: Config) = this()

  final override def create(owner: Option[ActorRef], system: Option[ActorSystem]): MessageQueue =
    new UnboundedMailboxWrapper.MessageQueue
}

object UnboundedMailboxWrapper {
  class MessageQueue extends ConcurrentLinkedQueue[Envelope] with UnboundedQueueBasedMessageQueue {
    val runtime = RuntimeManager.runtime
    final def queue: Queue[Envelope] = this
    override def enqueue(receiver: ActorRef, handle: Envelope): Unit = {
      runtime.queue.add(handle)
      queue add handle
    }
    override def dequeue(): Envelope = {
      if (!runtime.queue.isEmpty) runtime.mailbox.queue.poll()
      queue.poll()
    }
  }
}
在此邮箱中,我们将添加的元素复制到另一个队列中,因此在计算大小和对其执行其他操作时,不会对邮箱队列的性能产生任何影响

在重复队列中,我们可以计算消息的数量并对其进行排序:

def getElemets(): String = {
  runtime.queue.asScala.toList.groupBy(_.message.getClass.getName)
    .map(e ⇒ (e._1, e._2.length)).toSeq
    .sortBy(_._2).foldLeft("") { (a, b) ⇒
    b._1 + ":" + b._2 + "\n" + a
  }
}
使用JMX或任何其他方式,我们可以在运行时调用此方法

并最终将此邮箱分配给ShardRegion dispatcher:

monit-dispatcher {
  mailbox-type = "im.actor.server.cluster.UnboundedMailboxWrapper"
}

akka.cluster.sharding {
  use-dispatcher = "monit-dispatcher"
}

警告:您现在已经用java.util.concurrent.ConcurrentLinkedQueue完全替换了默认实现AbstractNodeQueue。请注意,默认设置是针对actor邮箱用例优化的,替换它可能会影响性能。这是akka.dispatch.UnboundedMailbox的实现,我刚刚复制了它。UnbounddMailbox的akka实现使用ConcurrentLinkedQueue。是的,你是对的,不知道我为什么想到抽象节点队列(它在调度程序中使用)。
对性能没有任何影响
可能是不正确的,但是,您正在用额外队列复制正在完成的工作和存储开销,而且额外队列必须在其他地方轮询,或者元素永远保存在内存中,即使这些元素被传给了演员,你说的永远留在记忆中的元素是什么意思?我们轮询了出列中的元素,当消息传递给参与者时,将调用此方法。计算队列的大小是有代价的,为了降低这些代价,我们会承受一些内存开销