我有一个演员系统,如下图所示。
Master
|
|--Monitor
|
|--Supervisor
|
|--Device #1
|--Device #2
|-- ...
|--Device #N
Master actor启动Monitor actor和Supervisor actor。
Monitor actor会发出一条消息,告诉自己每隔30秒检查一次设备清单。对于清单中存在的每个设备,它会向Supervisor actor发送一条消息以注册设备。
Supervisor actor在收到来自Monitor actor的消息注册设备时启动设备actor。
代码在github上可用here。
在单个JVM实例中,一切都运行良好,但是当涉及到群集模式时,我开始感到困惑。
正如我所料,通过以下配置,先前的actor树应该在群集机器中透明地运行。应该在整个集群中创建所有actor,我不应该关心创建actor的机器。
在实例#1上:
akka {
actor {
provider = "cluster"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2551
}
}
cluster {
seed-nodes = [
"akka.tcp://example@127.0.0.1:2551",
]
}
}
在实例#2上:
akka {
actor {
provider = "cluster"
}
remote {
log-remote-lifecycle-events = off
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
}
cluster {
seed-nodes = [
"akka.tcp://example@127.0.0.1:2551",
]
}
}
我的期望:
Master (On node 1)
|
|--Monitor (On node 2)
|
|--Supervisor (On node 2)
|
|--Device #1 (On node 1)
|--Device #2 (On node 1)
|-- ...
|--Device #N (On node 2)
但是,它最终会在集群中运行两个相同的actor树:每个节点分别运行一个actor树,如下图所示:
Node 1 | Node2
|
Master | Master
| | |
|--Monitor | |--Monitor
| | |
|--Supervisor | |--Supervisor
| | |
|--Device #1 | |--Device #1
|--Device #2 | |--Device #2
|-- ... | |-- ...
|--Device #N | |--Device #N
我还尝试将Master actor作为集群中的单例actor运行,但它最终在启动Master的节点上运行单个actor树。
所以,我的问题是,如何通过调用context.actorOf(DeviceActor.props(deviceId))
在整个集群中创建一个actor,而无需仔细设计具有集群单例和集群分片的actor树?
答案 0 :(得分:2)
您所描述的是Akka cluster sharding的确切定义。
当您需要在集群中的多个节点之间分配actor并希望能够使用其逻辑标识符与它们进行交互时,群集分片非常有用,但无需关心它们在群集中的物理位置,这可能也会发生变化随着时间的推移。
设置它非常简单,特别是如果你已经拥有一个集群。 Monitor将是一个Cluster Singleton,因此群集中只有一个是活动的,每个Device都是由设备ID标识的实体。