假设我有一个使用actor处理User的应用程序。因此每个用户有一个UserActor。此外,每个用户Actor通过id映射到用户,例如要处理具体用户的操作,你应该得到这样的Actor:
ActorSelection actor = actorSystem.actorSelection("/user/1");
其中 1 是用户ID。
所以问题是 - 如何有效地在集群内生成唯一的id?首先,它需要检查新的id不会复制现有的id。我可以为生成id 创建一个actor,它将存在于一个节点中,并且在创建任何新的UserActor Generator之前会要求id,但是这会在创建用户时在集群内部产生额外的请求。有没有办法更有效地做到这一点?是否有内置的akka技术来做到这一点?
P.S。愿这个使用Actor的架构无效,欢迎任何建议/最佳实践。
答案 0 :(得分:4)
我不会说你的方法是否是一个好主意。这取决于你决定。如果我确实理解你的问题,那么我可以建议一个高级的方法让它适合你。如果我理解正确,你就有了一个集群,对于任何给定的userId,系统中应该有一个处理请求的actor,它应该只在一个节点上,并且可以根据用户的用户ID一致地到达。如果这是正确的,那么请考虑以下方法。
让我们先从一个简单的演员开始吧,我们称之为UserRequestForwarder
。这个actor的工作是为特定用户id的请求找到一个actor实例并转发给它。如果该actor实例尚不存在,那么此actor将在转发之前创建它。粗略的草图可能如下所示:
class UserRequestForwarder extends Actor{
def receive = {
case req @ DoSomethingForUser(userId) =>
val childName = s"user-request-handler-$userId"
val child = context.child(childName).getOrElse(context.actorOf(Props[UserRequestHandler]))
child forward req
}
}
现在,这个actor将通过ConsistentHashingPool路由器部署到集群中的每个节点上,该路由器的配置方式是每个节点有一个实例。您只需要确保每个请求中都有需要通过此路由器的内容,以允许它一致地散列到处理该用户请求的节点(希望使用用户ID)
因此,如果您通过此路由器传递所有请求,它们将始终落在负责该用户的节点上,最后在UserRequestForwarder
,然后在该节点上找到正确的用户actor并传递要求它。
我自己没有尝试过这种方法,但如果我能正确理解你的问题,它可能适用于你想要做的事情。
答案 1 :(得分:1)
不是akka专家,因此我无法提供代码,但不应采用以下方法:
让一个演员负责创建演员。并且它保留了一个Hashset的演员名称,对于它创建的演员,并且已经没有死。
如果必须在多个actor之间分配负载,则可以根据必须创建的actor名称的哈希码的前n位来分派任务。
答案 2 :(得分:1)
您似乎对如何生成唯一ID有了答案。就更大的问题而言,这就是Akka集群分片旨在解决的问题。它将处理群集中的分片,在群集中查找或启动角色,甚至重新平衡。
http://doc.akka.io/docs/akka/2.3.5/contrib/cluster-sharding.html
还有一个非常好的例子。
http://typesafe.com/activator/template/akka-cluster-sharding-scala