2015-06-30 14:46:34 +02:00
|
|
|
.. _distributed-pub-sub-scala:
|
2013-04-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
Distributed Publish Subscribe in Cluster
|
|
|
|
|
========================================
|
|
|
|
|
|
|
|
|
|
How do I send a message to an actor without knowing which node it is running on?
|
|
|
|
|
|
|
|
|
|
How do I send messages to all actors in the cluster that have registered interest
|
|
|
|
|
in a named topic?
|
|
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
This pattern provides a mediator actor, ``akka.cluster.pubsub.DistributedPubSubMediator``,
|
2013-04-06 16:22:30 +02:00
|
|
|
that manages a registry of actor references and replicates the entries to peer
|
|
|
|
|
actors among all cluster nodes or a group of nodes tagged with a specific role.
|
|
|
|
|
|
2015-06-30 14:46:34 +02:00
|
|
|
The ``DistributedPubSubMediator`` actor is supposed to be started on all nodes,
|
2013-04-06 16:22:30 +02:00
|
|
|
or all nodes with specified role, in the cluster. The mediator can be
|
2015-06-30 14:46:34 +02:00
|
|
|
started with the ``DistributedPubSub`` extension or as an ordinary actor.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-06-30 14:46:34 +02:00
|
|
|
The registry is eventually consistent, i.e. changes are not immediately visible at
|
|
|
|
|
other nodes, but typically they will be fully replicated to all other nodes after
|
|
|
|
|
a few seconds. Changes are only performed in the own part of the registry and those
|
|
|
|
|
changes are versioned. Deltas are disseminated in a scalable way to other nodes with
|
|
|
|
|
a gossip protocol.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
Cluster members with status :ref:`WeaklyUp <weakly_up_scala>`, if that feature is enabled,
|
|
|
|
|
will participate in Distributed Publish Subscribe, i.e. subscribers on nodes with
|
|
|
|
|
``WeaklyUp`` status will receive published messages if the publisher and subscriber are on
|
|
|
|
|
same side of a network partition.
|
|
|
|
|
|
2013-04-06 16:22:30 +02:00
|
|
|
You can send messages via the mediator on any node to registered actors on
|
2015-09-11 15:48:49 +02:00
|
|
|
any other node.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
There a two different modes of message delivery, explained in the sections
|
|
|
|
|
:ref:`distributed-pub-sub-publish-scala` and :ref:`distributed-pub-sub-send-scala` below.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2016-02-23 12:58:39 +01:00
|
|
|
A more comprehensive sample is available in the `Lightbend Activator <http://www.lightbend.com/platform/getstarted>`_
|
|
|
|
|
tutorial named `Akka Clustered PubSub with Scala! <http://www.lightbend.com/activator/template/akka-clustering>`_.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
.. _distributed-pub-sub-publish-scala:
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
Publish
|
|
|
|
|
-------
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
This is the true pub/sub mode. A typical usage of this mode is a chat room in an instant
|
|
|
|
|
messaging application.
|
2014-04-04 12:10:41 +08:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
Actors are registered to a named topic. This enables many subscribers on each node.
|
|
|
|
|
The message will be delivered to all subscribers of the topic.
|
2014-04-04 12:10:41 +08:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
For efficiency the message is sent over the wire only once per node (that has a matching topic),
|
|
|
|
|
and then delivered to all subscribers of the local topic representation.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
You register actors to the local mediator with ``DistributedPubSubMediator.Subscribe``.
|
2013-04-06 16:22:30 +02:00
|
|
|
Successful ``Subscribe`` and ``Unsubscribe`` is acknowledged with
|
|
|
|
|
``DistributedPubSubMediator.SubscribeAck`` and ``DistributedPubSubMediator.UnsubscribeAck``
|
2015-09-11 15:48:49 +02:00
|
|
|
replies. The acknowledgment means that the subscription is registered, but it can still
|
|
|
|
|
take some time until it is replicated to other nodes.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
You publish messages by sending ``DistributedPubSubMediator.Publish`` message to the
|
|
|
|
|
local mediator.
|
2015-09-04 12:38:49 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
Actors are automatically removed from the registry when they are terminated, or you
|
|
|
|
|
can explicitly remove entries with ``DistributedPubSubMediator.Unsubscribe``.
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
An example of a subscriber actor:
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#subscriber
|
2013-04-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
Subscriber actors can be started on several nodes in the cluster, and all will receive
|
|
|
|
|
messages published to the "content" topic.
|
|
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#start-subscribers
|
2013-04-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
A simple actor that publishes to this "content" topic:
|
|
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#publisher
|
2013-04-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
It can publish messages to the topic from anywhere in the cluster:
|
|
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#publish-message
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-09-11 15:48:49 +02:00
|
|
|
Actors may also be subscribed to a named topic with an optional property (``group``).
|
|
|
|
|
If subscribing with a group name, each message published to a topic with the
|
|
|
|
|
(``sendOneMessageToEachGroup``) flag is delivered via the supplied ``RoutingLogic``
|
|
|
|
|
(default random) to one actor within each subscribing group.
|
|
|
|
|
If all the subscribed actors have the same group name, then this works just like
|
|
|
|
|
``Send`` and all messages are delivered to one subscriber.
|
|
|
|
|
If all the subscribed actors have different group names, then this works like
|
|
|
|
|
normal ``Publish`` and all messages are broadcast to all subscribers.
|
|
|
|
|
|
|
|
|
|
.. _distributed-pub-sub-send-scala:
|
|
|
|
|
|
|
|
|
|
Send
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
This is a point-to-point mode where each message is delivered to one destination,
|
|
|
|
|
but you still does not have to know where the destination is located.
|
|
|
|
|
A typical usage of this mode is private chat to one other user in an instant messaging
|
|
|
|
|
application. It can also be used for distributing tasks to registered workers, like a
|
|
|
|
|
cluster aware router where the routees dynamically can register themselves.
|
|
|
|
|
|
|
|
|
|
The message will be delivered to one recipient with a matching path, if any such
|
|
|
|
|
exists in the registry. If several entries match the path because it has been registered
|
|
|
|
|
on several nodes the message will be sent via the supplied ``RoutingLogic`` (default random)
|
|
|
|
|
to one destination. The sender() of the message can specify that local affinity is preferred,
|
|
|
|
|
i.e. the message is sent to an actor in the same local actor system as the used mediator actor,
|
|
|
|
|
if any such exists, otherwise route to any other matching entry.
|
|
|
|
|
|
|
|
|
|
You register actors to the local mediator with ``DistributedPubSubMediator.Put``.
|
|
|
|
|
The ``ActorRef`` in ``Put`` must belong to the same local actor system as the mediator.
|
|
|
|
|
The path without address information is the key to which you send messages.
|
|
|
|
|
On each node there can only be one actor for a given path, since the path is unique
|
|
|
|
|
within one local actor system.
|
|
|
|
|
|
|
|
|
|
You send messages by sending ``DistributedPubSubMediator.Send`` message to the
|
|
|
|
|
local mediator with the path (without address information) of the destination
|
|
|
|
|
actors.
|
|
|
|
|
|
|
|
|
|
Actors are automatically removed from the registry when they are terminated, or you
|
|
|
|
|
can explicitly remove entries with ``DistributedPubSubMediator.Remove``.
|
|
|
|
|
|
|
|
|
|
An example of a destination actor:
|
|
|
|
|
|
|
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#send-destination
|
|
|
|
|
|
|
|
|
|
Destination actors can be started on several nodes in the cluster, and all will receive
|
|
|
|
|
messages sent to the path (without address information).
|
|
|
|
|
|
|
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#start-send-destinations
|
|
|
|
|
|
|
|
|
|
A simple actor that sends to the path:
|
|
|
|
|
|
|
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#sender
|
|
|
|
|
|
|
|
|
|
It can send messages to the path from anywhere in the cluster:
|
|
|
|
|
|
|
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#send-message
|
|
|
|
|
|
|
|
|
|
It is also possible to broadcast messages to the actors that have been registered with
|
|
|
|
|
``Put``. Send ``DistributedPubSubMediator.SendToAll`` message to the local mediator and the wrapped message
|
|
|
|
|
will then be delivered to all recipients with a matching path. Actors with
|
|
|
|
|
the same path, without address information, can be registered on different nodes.
|
|
|
|
|
On each node there can only be one such actor, since the path is unique within one
|
|
|
|
|
local actor system.
|
|
|
|
|
|
|
|
|
|
Typical usage of this mode is to broadcast messages to all replicas
|
|
|
|
|
with the same path, e.g. 3 actors on different nodes that all perform the same actions,
|
|
|
|
|
for redundancy. You can also optionally specify a property (``allButSelf``) deciding
|
|
|
|
|
if the message should be sent to a matching path on the self node or not.
|
2014-02-21 11:24:01 +01:00
|
|
|
|
2015-06-30 14:46:34 +02:00
|
|
|
DistributedPubSub Extension
|
|
|
|
|
---------------------------
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-06-30 14:46:34 +02:00
|
|
|
In the example above the mediator is started and accessed with the ``akka.cluster.pubsub.DistributedPubSub`` extension.
|
2013-04-06 16:22:30 +02:00
|
|
|
That is convenient and perfectly fine in most cases, but it can be good to know that it is possible to
|
|
|
|
|
start the mediator actor as an ordinary actor and you can have several different mediators at the same
|
|
|
|
|
time to be able to divide a large number of actors/topics to different mediators. For example you might
|
|
|
|
|
want to use different cluster roles for different mediators.
|
|
|
|
|
|
2015-06-30 14:46:34 +02:00
|
|
|
The ``DistributedPubSub`` extension can be configured with the following properties:
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
.. includecode:: ../../../akka-cluster-tools/src/main/resources/reference.conf#pub-sub-ext-config
|
2013-04-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
It is recommended to load the extension when the actor system is started by defining it in
|
|
|
|
|
``akka.extensions`` configuration property. Otherwise it will be activated when first used
|
|
|
|
|
and then it takes a while for it to be populated.
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
2015-05-07 11:01:59 +02:00
|
|
|
akka.extensions = ["akka.cluster.pubsub.DistributedPubSub"]
|
2013-04-06 16:22:30 +02:00
|
|
|
|
2015-04-27 14:25:10 +02:00
|
|
|
Dependencies
|
|
|
|
|
------------
|
|
|
|
|
|
2015-12-26 23:56:41 -05:00
|
|
|
To use Distributed Publish Subscribe you must add the following dependency in your project.
|
2015-04-27 14:25:10 +02:00
|
|
|
|
|
|
|
|
sbt::
|
|
|
|
|
|
|
|
|
|
"com.typesafe.akka" %% "akka-cluster-tools" % "@version@" @crossString@
|
|
|
|
|
|
|
|
|
|
maven::
|
|
|
|
|
|
|
|
|
|
<dependency>
|
|
|
|
|
<groupId>com.typesafe.akka</groupId>
|
|
|
|
|
<artifactId>akka-cluster-tools_@binVersion@</artifactId>
|
|
|
|
|
<version>@version@</version>
|
|
|
|
|
</dependency>
|