!clt #13711 Move cluster tools from contrib

* new module akka-cluster-tools containing
  cluster singleton, distributed pub-sub, and cluster client
This commit is contained in:
Patrik Nordwall 2015-04-27 14:25:10 +02:00
parent c39e41c45b
commit fb72214d99
39 changed files with 792 additions and 683 deletions

View file

@ -0,0 +1,18 @@
import akka.{ AkkaBuild, Dependencies, Formatting, MultiNode, Unidoc, OSGi }
import com.typesafe.tools.mima.plugin.MimaKeys
AkkaBuild.defaultSettings
Formatting.formatSettings
Unidoc.scaladocSettingsNoVerificationOfDiagrams
Unidoc.javadocSettings
OSGi.clusterTools
MultiNode.multiJvmSettings
libraryDependencies ++= Dependencies.clusterTools
//MimaKeys.previousArtifact := akkaPreviousArtifact("akka-cluster-tools").value

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
option java_package = "akka.contrib.pattern.protobuf.msg";
option java_package = "akka.cluster.pubsub.protobuf.msg";
option optimize_for = SPEED;
message Status {

View file

@ -0,0 +1,77 @@
############################################
# Akka Cluster Tools Reference Config File #
############################################
# This is the reference config file that contains all the default settings.
# Make your edits/overrides in your application.conf.
# //#pub-sub-ext-config
# Settings for the DistributedPubSubExtension
akka.cluster.pub-sub {
# Actor name of the mediator actor, /user/distributedPubSubMediator
name = distributedPubSubMediator
# Start the mediator on members tagged with this role.
# All members are used if undefined or empty.
role = ""
# The routing logic to use for 'Send'
# Possible values: random, round-robin, broadcast
routing-logic = random
# How often the DistributedPubSubMediator should send out gossip information
gossip-interval = 1s
# Removed entries are pruned after this duration
removed-time-to-live = 120s
# Maximum number of elements to transfer in one message when synchronizing the registries.
# Next chunk will be transferred in next round of gossip.
max-delta-elements = 3000
}
# //#pub-sub-ext-config
# Protobuf serializer for cluster DistributedPubSubMeditor messages
akka.actor {
serializers {
akka-pubsub = "akka.cluster.pubsub.protobuf.DistributedPubSubMessageSerializer"
}
serialization-bindings {
"akka.cluster.pubsub.DistributedPubSubMessage" = akka-pubsub
}
serialization-identifiers {
"akka.cluster.pubsub.protobuf.DistributedPubSubMessageSerializer" = 9
}
}
# //#receptionist-ext-config
# Settings for the ClusterReceptionistExtension
akka.cluster.client.receptionist {
# Actor name of the ClusterReceptionist actor, /user/receptionist
name = receptionist
# Start the receptionist on members tagged with this role.
# All members are used if undefined or empty.
role = ""
# The receptionist will send this number of contact points to the client
number-of-contacts = 3
# The actor that tunnel response messages to the client will be stopped
# after this time of inactivity.
response-tunnel-receive-timeout = 30s
}
# //#receptionist-ext-config
# //#cluster-client-mailbox-config
akka.cluster.client {
mailbox {
mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox"
stash-capacity = 1000
}
}
# //#cluster-client-mailbox-config

View file

@ -1,7 +1,7 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.client
import java.net.URLEncoder
import scala.collection.immutable
@ -29,6 +29,7 @@ import akka.routing.ConsistentHash
import akka.routing.MurmurHash
import akka.actor.Stash
import akka.actor.Cancellable
import akka.cluster.pubsub._
object ClusterClient {
@ -40,7 +41,7 @@ object ClusterClient {
establishingGetContactsInterval: FiniteDuration = 3.second,
refreshContactsInterval: FiniteDuration = 1.minute): Props =
Props(classOf[ClusterClient], initialContacts, establishingGetContactsInterval, refreshContactsInterval).
withMailbox("akka.contrib.cluster.client.mailbox")
withMailbox("akka.cluster.client.mailbox")
/**
* Java API: Factory method for `ClusterClient` [[akka.actor.Props]].
@ -77,7 +78,7 @@ object ClusterClient {
/**
* INTERNAL API
*/
private[pattern] object Internal {
private[akka] object Internal {
case object RefreshContactsTick
}
}
@ -194,7 +195,7 @@ class ClusterClient(
/**
* Extension that starts [[ClusterReceptionist]] and accompanying [[DistributedPubSubMediator]]
* with settings defined in config section `akka.contrib.cluster.receptionist`.
* with settings defined in config section `akka.cluster.client.receptionist`.
* The [[DistributedPubSubMediator]] is started by the [[DistributedPubSubExtension]].
*/
object ClusterReceptionistExtension extends ExtensionId[ClusterReceptionistExtension] with ExtensionIdProvider {
@ -208,7 +209,7 @@ object ClusterReceptionistExtension extends ExtensionId[ClusterReceptionistExten
class ClusterReceptionistExtension(system: ExtendedActorSystem) extends Extension {
private val config = system.settings.config.getConfig("akka.contrib.cluster.receptionist")
private val config = system.settings.config.getConfig("akka.cluster.client.receptionist")
private val role: Option[String] = config.getString("role") match {
case "" None
case r Some(r)
@ -309,7 +310,7 @@ object ClusterReceptionist {
/**
* INTERNAL API
*/
private[pattern] object Internal {
private[akka] object Internal {
@SerialVersionUID(1L)
case object GetContacts
@SerialVersionUID(1L)

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.pubsub
import scala.collection.immutable
import scala.collection.immutable.Set
@ -137,7 +137,7 @@ object DistributedPubSubMediator {
/**
* INTERNAL API
*/
private[pattern] object Internal {
private[akka] object Internal {
case object Prune
@SerialVersionUID(1L)
@ -650,7 +650,7 @@ class DistributedPubSubMediator(
/**
* Extension that starts a [[DistributedPubSubMediator]] actor
* with settings defined in config section `akka.contrib.cluster.pub-sub`.
* with settings defined in config section `akka.cluster.pub-sub`.
*/
object DistributedPubSubExtension extends ExtensionId[DistributedPubSubExtension] with ExtensionIdProvider {
override def get(system: ActorSystem): DistributedPubSubExtension = super.get(system)
@ -663,7 +663,7 @@ object DistributedPubSubExtension extends ExtensionId[DistributedPubSubExtension
class DistributedPubSubExtension(system: ExtendedActorSystem) extends Extension {
private val config = system.settings.config.getConfig("akka.contrib.cluster.pub-sub")
private val config = system.settings.config.getConfig("akka.cluster.pub-sub")
private val role: Option[String] = config.getString("role") match {
case "" None
case r Some(r)

View file

@ -1,7 +1,7 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern.protobuf
package akka.cluster.pubsub.protobuf
import akka.serialization.BaseSerializer
import akka.cluster._
@ -17,12 +17,12 @@ import java.util.zip.GZIPOutputStream
import java.util.zip.GZIPInputStream
import com.google.protobuf.MessageLite
import scala.annotation.tailrec
import akka.contrib.pattern.protobuf.msg.{ DistributedPubSubMessages dm }
import akka.cluster.pubsub.protobuf.msg.{ DistributedPubSubMessages dm }
import scala.collection.JavaConverters._
import scala.concurrent.duration.Deadline
import akka.contrib.pattern.DistributedPubSubMessage
import akka.contrib.pattern.DistributedPubSubMediator._
import akka.contrib.pattern.DistributedPubSubMediator.Internal._
import akka.cluster.pubsub.DistributedPubSubMessage
import akka.cluster.pubsub.DistributedPubSubMediator._
import akka.cluster.pubsub.DistributedPubSubMediator.Internal._
import akka.serialization.Serialization
import akka.actor.ActorRef
import akka.serialization.SerializationExtension

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import scala.concurrent.duration._
import scala.collection.immutable
@ -317,7 +317,7 @@ class ClusterSingletonManagerIsStuck(message: String) extends AkkaException(mess
* reached. If the retry limit is reached it takes the decision to be
* the new oldest if previous oldest is unknown (typically removed),
* otherwise it initiates a new round by throwing
* [[akka.contrib.pattern.ClusterSingletonManagerIsStuck]] and expecting
* [[akka.cluster.singleton.ClusterSingletonManagerIsStuck]] and expecting
* restart with fresh state. For a cluster with many members you might
* need to increase this retry limit because it takes longer time to
* propagate changes across all nodes.
@ -328,7 +328,7 @@ class ClusterSingletonManagerIsStuck(message: String) extends AkkaException(mess
* oldest immediately, without knowing who was previous oldest. This is retried
* with the `retryInterval` until this retry limit has been reached. If the retry
* limit is reached it initiates a new round by throwing
* [[akka.contrib.pattern.ClusterSingletonManagerIsStuck]] and expecting
* [[akka.cluster.singleton.ClusterSingletonManagerIsStuck]] and expecting
* restart with fresh state. This will also cause the singleton actor to be
* stopped. `maxTakeOverRetries` must be less than `maxHandOverRetries` to
* ensure that new oldest doesn't start singleton actor before previous is

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import akka.actor._
import akka.cluster.{ MemberStatus, Cluster, Member }
@ -58,7 +58,7 @@ object ClusterSingletonProxy {
}
/**
* The `ClusterSingletonProxy` works together with the [[akka.contrib.pattern.ClusterSingletonManager]] to provide a
* The `ClusterSingletonProxy` works together with the [[akka.cluster.singleton.ClusterSingletonManager]] to provide a
* distributed proxy to the singleton actor.
*
* The proxy can be started on every node where the singleton needs to be reached and used as if it were the singleton

View file

@ -1,7 +1,7 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.client
import language.postfixOps
import scala.concurrent.duration._
@ -17,6 +17,7 @@ import akka.remote.testkit.MultiNodeSpec
import akka.remote.testkit.STMultiNodeSpec
import akka.testkit._
import akka.actor.Address
import akka.cluster.pubsub._
object ClusterClientSpec extends MultiNodeConfig {
val client = role("client")

View file

@ -1,7 +1,7 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.pubsub
import language.postfixOps
import scala.concurrent.duration._
@ -18,8 +18,8 @@ import akka.remote.testkit.MultiNodeSpec
import akka.remote.testkit.STMultiNodeSpec
import akka.testkit._
import akka.actor.ActorLogging
import akka.contrib.pattern.DistributedPubSubMediator.Internal.Status
import akka.contrib.pattern.DistributedPubSubMediator.Internal.Delta
import akka.cluster.pubsub.DistributedPubSubMediator.Internal.Status
import akka.cluster.pubsub.DistributedPubSubMediator.Internal.Delta
object DistributedPubSubMediatorSpec extends MultiNodeConfig {
val first = role("first")
@ -31,7 +31,7 @@ object DistributedPubSubMediatorSpec extends MultiNodeConfig {
akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
akka.remote.log-remote-lifecycle-events = off
akka.cluster.auto-down-unreachable-after = 0s
akka.contrib.cluster.pub-sub.max-delta-elements = 500
akka.cluster.pub-sub.max-delta-elements = 500
"""))
object TestChatUser {

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import language.postfixOps
import scala.collection.immutable

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import language.postfixOps
import scala.collection.immutable

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import language.postfixOps
import scala.collection.immutable

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import language.postfixOps
import scala.collection.immutable

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern;
package akka.cluster.pubsub;
import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.ClassRule;

View file

@ -2,7 +2,7 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern;
package akka.cluster.singleton;
import java.util.ArrayList;
import java.util.Comparator;

View file

@ -0,0 +1,6 @@
akka {
actor {
serialize-creators = on
serialize-messages = on
}
}

View file

@ -1,4 +1,4 @@
package akka.contrib.pattern
package akka.cluster.pubsub
import akka.testkit._
import akka.routing.{ ConsistentHashingRoutingLogic, RouterEnvelope }
@ -16,7 +16,7 @@ object DistributedPubSubMediatorRouterSpec {
akka.loglevel = INFO
akka.actor.provider = "akka.cluster.ClusterActorRefProvider"
akka.remote.log-remote-lifecycle-events = off
akka.contrib.cluster.pub-sub.routing-logic = $routingLogic
akka.cluster.pub-sub.routing-logic = $routingLogic
"""
}

View file

@ -1,12 +1,12 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern.protobuf
package akka.cluster.pubsub.protobuf
import akka.actor.{ ExtendedActorSystem, Address }
import akka.testkit.AkkaSpec
import akka.contrib.pattern.DistributedPubSubMediator._
import akka.contrib.pattern.DistributedPubSubMediator.Internal._
import akka.cluster.pubsub.DistributedPubSubMediator._
import akka.cluster.pubsub.DistributedPubSubMediator.Internal._
import akka.actor.Props
import scala.collection.immutable.TreeMap

View file

@ -1,7 +1,7 @@
/**
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.contrib.pattern
package akka.cluster.singleton
import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpecLike }
import akka.testkit.{ TestProbe, TestKit }

View file

@ -34,10 +34,7 @@ The Current List of Modules
throttle
jul
peek-mailbox
cluster-singleton
cluster-sharding
distributed-pub-sub
cluster-client
aggregator
receive-pipeline

View file

@ -5,74 +5,6 @@
# This is the reference config file that contains all the default settings.
# Make your edits/overrides in your application.conf.
# //#pub-sub-ext-config
# Settings for the DistributedPubSubExtension
akka.contrib.cluster.pub-sub {
# Actor name of the mediator actor, /user/distributedPubSubMediator
name = distributedPubSubMediator
# Start the mediator on members tagged with this role.
# All members are used if undefined or empty.
role = ""
# The routing logic to use for 'Send'
# Possible values: random, round-robin, broadcast
routing-logic = random
# How often the DistributedPubSubMediator should send out gossip information
gossip-interval = 1s
# Removed entries are pruned after this duration
removed-time-to-live = 120s
# Maximum number of elements to transfer in one message when synchronizing the registries.
# Next chunk will be transferred in next round of gossip.
max-delta-elements = 3000
}
# //#pub-sub-ext-config
# Protobuf serializer for cluster DistributedPubSubMeditor messages
akka.actor {
serializers {
akka-pubsub = "akka.contrib.pattern.protobuf.DistributedPubSubMessageSerializer"
}
serialization-bindings {
"akka.contrib.pattern.DistributedPubSubMessage" = akka-pubsub
}
serialization-identifiers {
"akka.contrib.pattern.protobuf.DistributedPubSubMessageSerializer" = 9
}
}
# //#receptionist-ext-config
# Settings for the ClusterReceptionistExtension
akka.contrib.cluster.receptionist {
# Actor name of the ClusterReceptionist actor, /user/receptionist
name = receptionist
# Start the receptionist on members tagged with this role.
# All members are used if undefined or empty.
role = ""
# The receptionist will send this number of contact points to the client
number-of-contacts = 3
# The actor that tunnel response messages to the client will be stopped
# after this time of inactivity.
response-tunnel-receive-timeout = 30s
}
# //#receptionist-ext-config
# //#cluster-client-mailbox-config
akka.contrib.cluster.client {
mailbox {
mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox"
stash-capacity = 1000
}
}
# //#cluster-client-mailbox-config
# //#sharding-ext-config

View file

@ -38,6 +38,7 @@ import akka.cluster.MemberStatus
import akka.pattern.ask
import akka.persistence._
import akka.cluster.ClusterEvent.ClusterDomainEvent
import akka.cluster.singleton.ClusterSingletonManager
/**
* This extension provides sharding functionality of actors in a cluster.

View file

@ -6,6 +6,9 @@ Networking
../common/cluster
cluster-usage
../scala/cluster-singleton
../scala/distributed-pub-sub
../scala/cluster-client
cluster-metrics
remoting
serialization

View file

@ -201,4 +201,14 @@ user defined main class and packaging with `sbt-native-packager <https://github.
or `Typesafe ConductR <http://typesafe.com/products/conductr>`_.
Please see :ref:`deployment-scenarios` for more information.
Cluster tools moved to separate module
======================================
The Cluster Singleton, Distributed Pub-Sub, and Cluster Client previously located in the ``akka-contrib``
jar is now moved to a separate module named ``akka-cluster-tools``. You need to replace this dependency
if you use any of these tools.
The classes changed package name from ``akka.contrib.pattern`` to ``akka.cluster.singleton``, ``akka.cluster.pubsub``
and ``akka.cluster.client``.
The configuration properties changed name to ``akka.cluster.pub-sub`` and ``akka.cluster.client``.

View file

@ -15,6 +15,8 @@ i.e. not necessarily the initial contact points. Also, note it's necessary to ch
``akka.remote.RemoteActorRefProvider`` or ``akka.cluster.ClusterActorRefProvider`` when using
the cluster client.
The receptionist is supposed to be started on all nodes, or all nodes with specified role,
in the cluster. The receptionist can be started with the ``ClusterReceptionistExtension``
or as an ordinary actor.
@ -57,7 +59,7 @@ handled in by the supervision strategy of the parent actor. The size of the buff
can be configured by the following ``stash-capacity`` setting of the mailbox that is
used by the ``ClusterClient`` actor.
.. includecode:: @contribSrc@/src/main/resources/reference.conf#cluster-client-mailbox-config
.. includecode:: ../../../akka-cluster-tools/src/main/resources/reference.conf#cluster-client-mailbox-config
An Example
----------
@ -65,21 +67,21 @@ An Example
On the cluster nodes first start the receptionist. Note, it is recommended to load the extension
when the actor system is started by defining it in the ``akka.extensions`` configuration property::
akka.extensions = ["akka.contrib.pattern.ClusterReceptionistExtension"]
akka.extensions = ["akka.cluster.client.ClusterReceptionistExtension"]
Next, register the actors that should be available for the client.
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala#server
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala#server
On the client you create the ``ClusterClient`` actor and use it as a gateway for sending
messages to the actors identified by their path (without address information) somewhere
in the cluster.
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala#client
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala#client
The ``initialContacts`` parameter is a ``Set[ActorSelection]``, which can be created like this:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterClientSpec.scala#initialContacts
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/client/ClusterClientSpec.scala#initialContacts
You will probably define the address information of the initial contact points in configuration or system property.
@ -90,14 +92,14 @@ and `Distributed workers with Akka and Java! <http://www.typesafe.com/activator/
ClusterReceptionistExtension
----------------------------
In the example above the receptionist is started and accessed with the ``akka.contrib.pattern.ClusterReceptionistExtension``.
In the example above the receptionist is started and accessed with the ``akka.cluster.client.ClusterReceptionistExtension``.
That is convenient and perfectly fine in most cases, but it can be good to know that it is possible to
start the ``akka.contrib.pattern.ClusterReceptionist`` actor as an ordinary actor and you can have several
start the ``akka.cluster.client.ClusterReceptionist`` actor as an ordinary actor and you can have several
different receptionists at the same time, serving different types of clients.
The ``ClusterReceptionistExtension`` can be configured with the following properties:
.. includecode:: @contribSrc@/src/main/resources/reference.conf#receptionist-ext-config
.. includecode:: ../../../akka-cluster-tools/src/main/resources/reference.conf#receptionist-ext-config
Note that the ``ClusterReceptionistExtension`` uses the ``DistributedPubSubExtension``, which is described
in :ref:`distributed-pub-sub`.
@ -105,5 +107,21 @@ in :ref:`distributed-pub-sub`.
It is recommended to load the extension when the actor system is started by defining it in the
``akka.extensions`` configuration property::
akka.extensions = ["akka.contrib.pattern.ClusterReceptionistExtension"]
akka.extensions = ["akka.cluster.client.ClusterReceptionistExtension"]
Dependencies
------------
To use the Cluster Client you must add the following dependency in your project.
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>

View file

@ -19,7 +19,7 @@ such as single-point of bottleneck. Single-point of failure is also a relevant c
but for some cases this feature takes care of that by making sure that another singleton
instance will eventually be started.
The cluster singleton pattern is implemented by ``akka.contrib.pattern.ClusterSingletonManager``.
The cluster singleton pattern is implemented by ``akka.cluster.singleton.ClusterSingletonManager``.
It manages one singleton actor instance among all cluster nodes or a group of nodes tagged with
a specific role. ``ClusterSingletonManager`` is an actor that is supposed to be started on
all nodes, or all nodes with specified role, in the cluster. The actual singleton actor is
@ -38,7 +38,7 @@ take over and a new singleton actor is created. For these failure scenarios ther
not be a graceful hand-over, but more than one active singletons is prevented by all
reasonable means. Some corner cases are eventually resolved by configurable timeouts.
You can access the singleton actor by using the provided ``akka.contrib.pattern.ClusterSingletonProxy``,
You can access the singleton actor by using the provided ``akka.cluster.singleton.ClusterSingletonProxy``,
which will route all messages to the current instance of the singleton. The proxy will keep track of
the oldest node in the cluster and resolve the singleton's ``ActorRef`` by explicitly sending the
singleton's ``actorSelection`` the ``akka.actor.Identify`` message and waiting for it to reply.
@ -83,18 +83,18 @@ supply the ``Props`` of the singleton actor, in this case the JMS queue consumer
In Scala:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala#create-singleton-manager
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala#create-singleton-manager
Here we limit the singleton to nodes tagged with the ``"worker"`` role, but all nodes, independent of
role, can be used by specifying ``None`` as ``role`` parameter.
The corresponding Java API for the ``singeltonProps`` function is ``akka.contrib.pattern.ClusterSingletonPropsFactory``.
The corresponding Java API for the ``singeltonProps`` function is ``akka.cluster.singleton.ClusterSingletonPropsFactory``.
The Java API takes a plain String for the role parameter and ``null`` means that all nodes, independent of
role, are used.
In Java:
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/ClusterSingletonManagerTest.java#create-singleton-manager
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/singleton/ClusterSingletonManagerTest.java#create-singleton-manager
.. note::
@ -108,7 +108,7 @@ perfectly fine ``terminationMessage`` if you only need to stop the actor.
Here is how the singleton actor handles the ``terminationMessage`` in this example.
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala#consumer-end
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala#consumer-end
Note that you can send back current state to the ``ClusterSingletonManager`` before terminating.
This message will be sent over to the ``ClusterSingletonManager`` at the new oldest node and it
@ -119,14 +119,29 @@ configured proxy.
In Scala:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/ClusterSingletonManagerSpec.scala#create-singleton-proxy
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/singleton/ClusterSingletonManagerSpec.scala#create-singleton-proxy
In Java:
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/ClusterSingletonManagerTest.java#create-singleton-proxy
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/singleton/ClusterSingletonManagerTest.java#create-singleton-proxy
A more comprehensive sample is available in the `Typesafe Activator <http://www.typesafe.com/platform/getstarted>`_
tutorial named `Distributed workers with Akka and Scala! <http://www.typesafe.com/activator/template/akka-distributed-workers>`_
and `Distributed workers with Akka and Java! <http://www.typesafe.com/activator/template/akka-distributed-workers-java>`_.
Dependencies
------------
To use the Cluster Singleton you must add the following dependency in your project.
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>

View file

@ -8,7 +8,7 @@ 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?
This pattern provides a mediator actor, ``akka.contrib.pattern.DistributedPubSubMediator``,
This pattern provides a mediator actor, ``akka.cluster.pubsub.DistributedPubSubMediator``,
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.
@ -84,40 +84,40 @@ A Small Example in Java
A subscriber actor:
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java#subscriber
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/pubsub/DistributedPubSubMediatorTest.java#subscriber
Subscriber actors can be started on several nodes in the cluster, and all will receive
messages published to the "content" topic.
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java#start-subscribers
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/pubsub/DistributedPubSubMediatorTest.java#start-subscribers
A simple actor that publishes to this "content" topic:
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java#publisher
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/pubsub/DistributedPubSubMediatorTest.java#publisher
It can publish messages to the topic from anywhere in the cluster:
.. includecode:: @contribSrc@/src/test/java/akka/contrib/pattern/DistributedPubSubMediatorTest.java#publish-message
.. includecode:: ../../../akka-cluster-tools/src/test/java/akka/cluster/pubsub/DistributedPubSubMediatorTest.java#publish-message
A Small Example in Scala
------------------------
A subscriber actor:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala#subscriber
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#subscriber
Subscriber actors can be started on several nodes in the cluster, and all will receive
messages published to the "content" topic.
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala#start-subscribers
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#start-subscribers
A simple actor that publishes to this "content" topic:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala#publisher
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#publisher
It can publish messages to the topic from anywhere in the cluster:
.. includecode:: @contribSrc@/src/multi-jvm/scala/akka/contrib/pattern/DistributedPubSubMediatorSpec.scala#publish-message
.. includecode:: ../../../akka-cluster-tools/src/multi-jvm/scala/akka/cluster/pubsub/DistributedPubSubMediatorSpec.scala#publish-message
A more comprehensive sample is available in the `Typesafe Activator <http://www.typesafe.com/platform/getstarted>`_
tutorial named `Akka Clustered PubSub with Scala! <http://www.typesafe.com/activator/template/akka-clustering>`_.
@ -125,7 +125,7 @@ tutorial named `Akka Clustered PubSub with Scala! <http://www.typesafe.com/activ
DistributedPubSubExtension
--------------------------
In the example above the mediator is started and accessed with the ``akka.contrib.pattern.DistributedPubSubExtension``.
In the example above the mediator is started and accessed with the ``akka.cluster.pubsub.DistributedPubSubExtension``.
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
@ -133,7 +133,7 @@ want to use different cluster roles for different mediators.
The ``DistributedPubSubExtension`` can be configured with the following properties:
.. includecode:: @contribSrc@/src/main/resources/reference.conf#pub-sub-ext-config
.. includecode:: ../../../akka-cluster-tools/src/main/resources/reference.conf#pub-sub-ext-config
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
@ -141,5 +141,21 @@ and then it takes a while for it to be populated.
::
akka.extensions = ["akka.contrib.pattern.DistributedPubSubExtension"]
akka.extensions = ["akka.cluster.pubsub.DistributedPubSubExtension"]
Dependencies
------------
To use the Cluster Singleton you must add the following dependency in your project.
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>

View file

@ -6,6 +6,9 @@ Networking
../common/cluster
cluster-usage
cluster-singleton
distributed-pub-sub
cluster-client
cluster-metrics
remoting
serialization

View file

@ -18,7 +18,7 @@ val project = Project(
"com.typesafe.akka" %% "akka-remote" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster-metrics" % akkaVersion,
"com.typesafe.akka" %% "akka-contrib" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster-tools" % akkaVersion,
"com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion,
"org.scalatest" %% "scalatest" % "2.2.1" % "test",
"io.kamon" % "sigar-loader" % "1.6.5-rev001"),

View file

@ -6,8 +6,8 @@ import com.typesafe.config.ConfigFactory;
import akka.actor.ActorSystem;
import akka.actor.PoisonPill;
import akka.actor.Props;
import akka.contrib.pattern.ClusterSingletonManager;
import akka.contrib.pattern.ClusterSingletonProxy;
import akka.cluster.singleton.ClusterSingletonManager;
import akka.cluster.singleton.ClusterSingletonProxy;
public class StatsSampleOneMasterMain {

View file

@ -14,8 +14,8 @@ import akka.cluster.Member
import akka.cluster.MemberStatus
import akka.cluster.ClusterEvent.CurrentClusterState
import akka.cluster.ClusterEvent.MemberUp
import akka.contrib.pattern.ClusterSingletonManager
import akka.contrib.pattern.ClusterSingletonProxy
import akka.cluster.singleton.ClusterSingletonManager
import akka.cluster.singleton.ClusterSingletonProxy
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit.ImplicitSender

View file

@ -17,7 +17,7 @@ val project = Project(
"com.typesafe.akka" %% "akka-remote" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster-metrics" % akkaVersion,
"com.typesafe.akka" %% "akka-contrib" % akkaVersion,
"com.typesafe.akka" %% "akka-cluster-tools" % akkaVersion,
"com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion,
"org.scalatest" %% "scalatest" % "2.2.1" % "test",
"io.kamon" % "sigar-loader" % "1.6.5-rev001"),

View file

@ -4,8 +4,8 @@ import com.typesafe.config.ConfigFactory
import akka.actor.ActorSystem
import akka.actor.PoisonPill
import akka.actor.Props
import akka.contrib.pattern.ClusterSingletonManager
import akka.contrib.pattern.ClusterSingletonProxy
import akka.cluster.singleton.ClusterSingletonManager
import akka.cluster.singleton.ClusterSingletonProxy
object StatsSampleOneMaster {
def main(args: Array[String]): Unit = {

View file

@ -9,8 +9,8 @@ import org.scalatest.Matchers
import akka.actor.PoisonPill
import akka.actor.Props
import akka.actor.RootActorPath
import akka.contrib.pattern.ClusterSingletonManager
import akka.contrib.pattern.ClusterSingletonProxy
import akka.cluster.singleton.ClusterSingletonManager
import akka.cluster.singleton.ClusterSingletonProxy
import akka.cluster.Cluster
import akka.cluster.Member
import akka.cluster.MemberStatus

View file

@ -55,7 +55,7 @@ object AkkaBuild extends Build {
archivesPathFinder.get.map(file => (file -> ("akka/" + file.getName)))
}
),
aggregate = Seq(actor, testkit, actorTests, remote, remoteTests, camel, cluster, clusterMetrics, slf4j, agent,
aggregate = Seq(actor, testkit, actorTests, remote, remoteTests, camel, cluster, clusterMetrics, clusterTools, slf4j, agent,
persistence, persistenceTck, kernel, osgi, docs, contrib, samples, multiNodeTestkit, typed)
)
@ -64,7 +64,7 @@ object AkkaBuild extends Build {
base = file("akka-scala-nightly"),
// remove dependencies that we have to build ourselves (Scala STM)
// samples don't work with dbuild right now
aggregate = Seq(actor, testkit, actorTests, remote, remoteTests, camel, cluster, slf4j,
aggregate = Seq(actor, testkit, actorTests, remote, remoteTests, camel, cluster, clusterMetrics, clusterTools, slf4j,
persistence, persistenceTck, kernel, osgi, contrib, multiNodeTestkit, typed)
).disablePlugins(ValidatePullRequest)
@ -127,6 +127,12 @@ object AkkaBuild extends Build {
dependencies = Seq(cluster % "compile->compile;test->test;multi-jvm->multi-jvm", slf4j % "test->compile")
) configs (MultiJvm)
lazy val clusterTools = Project(
id = "akka-cluster-tools",
base = file("akka-cluster-tools"),
dependencies = Seq(cluster % "compile->compile;test->test;multi-jvm->multi-jvm")
) configs (MultiJvm)
lazy val slf4j = Project(
id = "akka-slf4j",
base = file("akka-slf4j"),
@ -181,7 +187,7 @@ object AkkaBuild extends Build {
lazy val contrib = Project(
id = "akka-contrib",
base = file("akka-contrib"),
dependencies = Seq(remote, remoteTests % "test->test", cluster, persistence % "compile;test->provided")
dependencies = Seq(remote, remoteTests % "test->test", cluster, clusterTools, persistence % "compile;test->provided")
) configs (MultiJvm)
lazy val samples = Project(

View file

@ -87,6 +87,8 @@ object Dependencies {
val remoteTests = deps(Test.junit, Test.scalatest, Test.scalaXml)
val cluster = Seq(Test.junit, Test.scalatest)
val clusterTools = Seq(Test.junit, Test.scalatest)
val clusterMetrics = Seq(Provided.sigarLoader, Test.slf4jJul, Test.slf4jLog4j, Test.logback, Test.mockito)

View file

@ -27,6 +27,9 @@ object OSGi {
val camel = exports(Seq("akka.camel.*"))
val cluster = exports(Seq("akka.cluster.*"), imports = Seq(protobufImport()))
val clusterTools = exports(Seq("akka.cluster.singleton.*", "akka.cluster.client.*", "akka.cluster.pubsub.*"),
imports = Seq(protobufImport()))
val clusterMetrics = exports(Seq("akka.cluster.metrics.*"), imports = Seq(protobufImport(),kamonImport(),sigarImport()))