在Akka群集示例,文档和教程中,似乎只有知道群集和群集的种子节点,任何节点都可以加入群集。如何防止未授权的节点加入?
答案 0 :(得分:1)
我试图实现此功能,但在Akka群集中也未找到此功能。我设法通过在角色上创建授权标志,将集群包装在Option[Cluster]
中,并决定在preStart()
方法中对集群上的角色进行订阅或不订阅。这已经阻止了参与者接收消息。但是,它仍然可以向集群成员发送消息。然后,将标志放在case UserMessage(content) if (authorized) => ???
上。我没有把演员踢出集群,但我相信这只是他踢完之后的踢腿。
object Alice extends ChatApp("Alice", 2551, true)
object Bob extends ChatApp("Bob", 2552, true)
object Fabio extends ChatApp("Fabio", 2554, false)
演员
class ChatActor(nickname: String, port: Int, authorized: Boolean) extends Actor with ActorLogging {
// 1: initialize the cluster object
val cluster: Option[Cluster] = if (authorized) Some(Cluster(context.system)) else None
// 2: subscribe to cluster event in preStart
override def preStart(): Unit = {
if (authorized) {
cluster match {
case Some(c) => c.subscribe(
self,
initialStateMode = InitialStateAsEvents,
classOf[MemberEvent]
)
case None => log.info(s"user [$nickname] is not authorized to enter in the cluster =(. Please leave the cluster.")
}
}
}
// 3: unsubscribe self in postStop
override def postStop(): Unit = {
cluster match {
case Some(c) => c.unsubscribe(self)
case None => log.info(s"user [$nickname] is not authorized to enter in the cluster =(.")
}
}
override def receive: Receive = online(Map())
/** chatRoom is the data structure to the users in the chat */
def online(chatRoom: Map[String, String]): Receive = {
case UserMessage(content) if (authorized) =>
chatRoom.keys.foreach { address =>
val chatActorSelection: ActorSelection = context.actorSelection(s"${address}/user/chatActor")
chatActorSelection ! ChatMessage(nickname, content)
}
}
}