如何跨 Akka 集群透明地创建参与者
How to create actors transparently across an Akka cluster
我有一个演员系统,如下图所示。
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。
代码可用 here github。
在单个 JVM 实例中一切都很好,但是当涉及到集群模式时,我开始感到困惑。
如我所料,通过以下配置,先前的 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 树?
你描述的是Akka cluster sharding的准确定义。
Cluster sharding is useful when you need to distribute actors across several nodes in the cluster and want to be able to interact with them using their logical identifier, but without having to care about their physical location in the cluster, which might also change over time.
设置起来非常简单,特别是如果您已经有一个集群。 Monitor 将是一个 Cluster Singleton,因此集群上只有一个活动,并且每个 Device 将是一个由设备 ID 标识的 entity。
我有一个演员系统,如下图所示。
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。
代码可用 here github。
在单个 JVM 实例中一切都很好,但是当涉及到集群模式时,我开始感到困惑。
如我所料,通过以下配置,先前的 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 树?
你描述的是Akka cluster sharding的准确定义。
Cluster sharding is useful when you need to distribute actors across several nodes in the cluster and want to be able to interact with them using their logical identifier, but without having to care about their physical location in the cluster, which might also change over time.
设置起来非常简单,特别是如果您已经有一个集群。 Monitor 将是一个 Cluster Singleton,因此集群上只有一个活动,并且每个 Device 将是一个由设备 ID 标识的 entity。