Distributed Pub-Sub
Distributed pub-sub can be achieved in akka cluster using mediator actor, akka.cluster.pubsub.DistributedPubSubMediator
This mediator actor is supposed to be started on all the nodes in the cluster (or nodes tagged with a specific role). It manages a registry of subscribers (actor references) to various topics and replicates that registry across the cluster using gossip protocol, which means it is eventually consistent.
Subscribe/Unsubscribe
Actors subscribe to a named topic by sending DistributedPubSubMediator.Subscribe
message to the local mediator actor. Successful subscribe and unsubscribe is acknowledged using DistributedPubSubMediator.SubscribeAck
and DistributedPubSubMediator.UnsubscribeAck
replies. The acknowledgement means that subscription is registered but it can take some time to replicate to other nodes in the cluster.
class Subscriber extends Actor with ActorLogging {
import DistributedPubSubMediator.{ Subscribe, SubscribeAck }
val mediator = DistributedPubSub(context.system).mediator
// subscribe to the topic named "content"
mediator ! Subscribe("content", self)
def receive = {
case s: String ⇒
log.info("Got {}", s)
case SubscribeAck(Subscribe("content", None, `self`)) ⇒
log.info("subscribing")
}
}
Actors are automatically removed from the registered when they are terminated or you can explicitly unsubscribe using DistributedPubSubMediator.Unsubscribe
message to local mediator.
Publish
Messages are published by sending DistributedPubSubMediator.Publish
message to the local mediator, which in turn sends the message to all matching subscribers using the subscription registry. For efficiency, messages are sent over the wire only once per node and then delivered to all the subscribers on that node.
class Publisher extends Actor {
import DistributedPubSubMediator.Publish
// activate the extension
val mediator = DistributedPubSub(context.system).mediator
def receive = {
case in: String ⇒
val out = in.toUpperCase
mediator ! Publish("content", out)
}
}
Topic Groups
When subscribing to a topic, you can additionally specify a group id. It can be used to define subscriber groups within a topic. When publishing a message, you can specify a flag sendOneMessageToEachGroup
which is set to true or false.
sendOneMessageToEachGroup=false or not specified
Message will not be delivered to subscribers that subscribed with a group id.
sendOneMessageToEachGroup=true
Message will be sent to one actor in each group. Which actor is picked from a group is dictated by the akka.cluster.pub-sub.routing-logic
config which can be the following:
random
default, will pick actor randomly from the groupround-robin
will pick actors in round robin fashionbroadcast
will send message to all the actors who have specified a group id
In Summary:
Subscribe without groupId | Subscribe with groupId | |
---|---|---|
Publish | Send to each subscriber | Ignored |
Publish(sendOneMessageToEachGroup=false) | Send to each subscriber | Ignored |
Publish(sendOneMessageToEachGroup=true) | Ignored | Send to one subscriber per group id |