如何知道演员是否闲置

时间:2012-07-07 17:52:38

标签: java actor akka

我有一些未知数量的工作要由已知(当然)数量的演员执行。演员完成工作后,初始职位数可能会增加。也就是说,演员在完成任务后,可能会添加一个要执行的新作业。

我处理这个问题的方法是让每个actor在完成其工作时向主服务器发送一条消息,不仅包括执行结果,还包含一个表示该actor现在处于空闲状态的'flag'。主人有一个工作队列和一个空闲的演员队列,每当一个演员发送一个“工作完成的消息”时,主人将检查该演员是否还有其他事情......等等直到工作队列是空的,空闲的队列已经满了......此时我关闭了系统。这里没有太多的监督,所以我觉得我做得不好......

我没有使用路由器,因为我找不到查询路由器空闲演员的方法,所以我的问题是:

处理我在Akka上面描述过的情况的“正确”方法是什么?

3 个答案:

答案 0 :(得分:7)

你应该看看Akka's routing capabilites. SmallestMailboxRouter可能正是你要找的。

作为替代方案,您可以按需创建actor,即对于每个任务,动态创建新actor。中央演员跟踪当前活动的所有演员。完成一个工作者后,它会向自己发送一个PoisonPill并通知主人关闭它(主动,或通过Akka将发送给监督演员的标准Terminate消息)。一旦没有更多活跃的角色,即没有更多的任务,控制者就会关闭系统。

阅读评论后添加: 看一下SmallestMailboxLike的来源,SmallestMailboxRouter混合的Scala特征。isProcessingMessage(ActorRef)。警告:您应该具备Scala的基本知识。但是如果你想使用Akka,这通常是一个好主意......方法isNotIdle(ActorRef)可以被理解为// Returns true if the actor is currently processing a message. // It will always return false for remote actors. // Method is exposed to subclasses to be able to implement custom // routers based on mailbox and actor internal state. protected def isProcessingMessage(a: ActorRef): Boolean = a match { case x: LocalActorRef ? val cell = x.underlying cell.mailbox.isScheduled && cell.currentMessage != null case _ ? false } // Returns true if the actor currently has any pending messages // in the mailbox, i.e. the mailbox is not empty. // It will always return false for remote actors. // Method is exposed to subclasses to be able to implement custom // routers based on mailbox and actor internal state. protected def hasMessages(a: ActorRef): Boolean = a match { case x: LocalActorRef ? x.underlying.mailbox.hasMessages case _ ? false }

{{1}}

答案 1 :(得分:1)

另一种策略可以是使用BalancingDispatcher和RoundRobinRouter(作为actor“池”)。来自Akka docs:

BalancingDispatcher
# This is an executor based event driven dispatcher that will try to redistribute work from busy actors to idle actors.




# All the actors share a single Mailbox that they get their messages from.

It is assumed that all actors using the same instance of this dispatcher can process all messages that have been sent to one of the actors; i.e. the actors belong to a pool of actors, and to the client there is no guarantee about which actor instance actually processes a given message.

# Sharability: Actors of the same type only

# Mailboxes: Any, creates one for all Actors

# Use cases: Work-sharing

在application.conf中定义调度程序或在启动时以编程方式加载它。

private final static Config akkaConfig = ConfigFactory.parseString(

            "my-dispatcher.type = BalancingDispatcher \n" +
            "my-dispatcher.executor = fork-join-executor \n" +
            "my-dispatcher.fork-join-executor.parallelism-min = 8 \n" +
            "my-dispatcher.fork-join-executor.parallelism-factor = 3.0 \n" +
            "my-dispatcher.fork-join-executor.parallelism-max = 64 "
);

然后为路由定义路由器和调度程序。

getContext().actorOf(new Props(MyActor.class).withRouter(new RoundRobinRouter(10)).withDispatcher("my-dispatcher"), "myActor");

因此,路由器将继续“分发”消息,并且调度程序将运行选定的actor(并且它也实现了工作窃取)

答案 2 :(得分:-1)

Balancing调度程序将仅为所有已创建的actor使用一个邮箱,这些actor都是使用BalancingDispatcher创建的。所以它会让你的工作变得简单。