Distributed Publish Subscribe in Cluster
通過了解Akka集群后,我們可能會產(chǎn)生兩個問題
如果我們要發(fā)送消息到某個actor但是我們不知道它在哪個節(jié)點運行,該如何發(fā)送?
如果我們要給訂閱某種Topic的所有actor發(fā)送消息,該如何發(fā)送?
于是Akka提供了一個中介actor:
akka.cluster.pubsub.DistributedPubSubMediator
它在所有的節(jié)點上啟動,用來管理actor引用的注冊表(比如,將actor的id與其actorRef對應(yīng)存入Map中 )。而且這些注冊表是具有最終一致性,當某個節(jié)點發(fā)生變化,這個節(jié)點上的mediator不會立即通知其他節(jié)點,而是將變化的信息進行版本化,幾秒后通過gossip 協(xié)議將變化的增量 復(fù)制到其他節(jié)點的mediator。
因此你就可以通過任意一個節(jié)點上的mediator 來向任何其他節(jié)點的actor通信
對于一開始的兩個問題,mediator有兩種消息傳遞模式:Publish與Send,下面將介紹具體的實現(xiàn)方法和過程。
Publish
這是一種 Pub/Sub 模式(如聊天室),
通過DistributedPubSubMediator.Subscribe方法來將訂閱這個主題的actor注冊到本地的mediator中。
通過 DistributedPubSubMediator.SubscribeAck ? 和DistributedPubSubMediator.UnSubscribeAck 確認是否訂閱成功,一段時間后會將該訂閱變化復(fù)制到其他節(jié)點的mediator
最后我們向本地的mediator發(fā)送DistributedPubSubMediator.Publish就可以將消息發(fā)布給所有訂閱的actor
如果actor被終止,它將在訂閱的注冊表中被自動移除。
actor也可以用group id 來進行訂閱,發(fā)布的這個主題的消息就會向每個group中隨機選一個actor發(fā)送。如果恰好訂閱消息的都是同一個group 的actor。那么mediator只需要發(fā)送到其中一個actor就可以。
使用sendOneMessageToEachGroup? (true/false)可以設(shè)置是否將消息發(fā)送給使用group id訂閱的actor。
Send
則是一個 point-to-point 模式(例如 私聊),每個消息都會投遞到一個目的地,即使你不知道目的地在哪里。
發(fā)送的消息會通過一個匹配路徑(因為不知道目的地在哪,所以該路徑不帶有地址信息)來發(fā)給mediator。節(jié)點中的每個actor通過DistributedPubSubMediator.Put?將其ActorRef注冊到本地的mediator中,所以在本地actor system中路徑是唯一的,通過path關(guān)鍵字即可找到目的actor。
換句話說,匹配路徑(path)=邏輯路徑,地址信息(address)=物理路徑。mediator 通過將帶有邏輯路徑的消息廣播給各個節(jié)點actor system。因為在每個actor system中actor 的路徑是唯一的,所以消息只需要知道actor的邏輯路徑就可以找到相應(yīng)的actor來發(fā)送消息。
如果有多個actor與path匹配(具有相同path的actor可以在不同的節(jié)點上注冊),將使用RoutingLogic (默認隨機)發(fā)送到其中一個。(可以設(shè)置本地偏好,優(yōu)先選擇本地的mediator進行發(fā)送)
用DistributedPubSubMediator.Send發(fā)給mediator帶有path的消息
同樣如果某個actor被終止,它將會在注冊表中自動刪除。
如果DistributedPubSubMediator.SendToAll ,可以實現(xiàn)消息廣播,將消息發(fā)給所有匹配路徑的actor
實現(xiàn)上面的兩種模式都是通過mediator擴展DistributedPubSub 來實現(xiàn),當然mediator也可以是一個普通的actor。
akka.extensions = ["akka.cluster.pubsub.DistributedPubSub"]
在分布式發(fā)布訂閱模式中只保證at-most-once delivery ,因此消息可能會丟失。
如果想要at-least-once投遞保證,推薦Kafka Akka Streams integration
依賴
sbt:
"com.typesafe.akka" %% "akka-cluster-tools" % "2.4.16"
maven:??