=clu #13802 Introduce max-total-nr-of-instances for cluster aware routers

This commit is contained in:
Patrik Nordwall 2015-08-20 15:13:35 +02:00
parent 12bee9433e
commit bc13e1b4c2
23 changed files with 77 additions and 41 deletions

View file

@ -21,6 +21,7 @@ import akka.cluster.ClusterEvent.CurrentClusterState
import akka.dispatch.Dispatchers import akka.dispatch.Dispatchers
import akka.japi.Util.immutableSeq import akka.japi.Util.immutableSeq
import akka.routing._ import akka.routing._
import akka.cluster.routing.ClusterRouterSettingsBase
/** /**
* Load balancing of messages to cluster nodes based on cluster metric data. * Load balancing of messages to cluster nodes based on cluster metric data.
@ -128,7 +129,7 @@ final case class AdaptiveLoadBalancingPool(
extends Pool { extends Pool {
def this(config: Config, dynamicAccess: DynamicAccess) = def this(config: Config, dynamicAccess: DynamicAccess) =
this(nrOfInstances = config.getInt("nr-of-instances"), this(nrOfInstances = ClusterRouterSettingsBase.getMaxTotalNrOfInstances(config),
metricsSelector = MetricsSelector.fromConfig(config, dynamicAccess), metricsSelector = MetricsSelector.fromConfig(config, dynamicAccess),
usePoolDispatcher = config.hasPath("pool-dispatcher")) usePoolDispatcher = config.hasPath("pool-dispatcher"))

View file

@ -208,12 +208,20 @@ akka {
# Maximum number of routees that will be deployed on each cluster # Maximum number of routees that will be deployed on each cluster
# member node. # member node.
# Note that nr-of-instances defines total number of routees, but # Note that max-total-nr-of-instances defines total number of routees, but
# number of routees per node will not be exceeded, i.e. if you # number of routees per node will not be exceeded, i.e. if you
# define nr-of-instances = 50 and max-nr-of-instances-per-node = 2 # define max-total-nr-of-instances = 50 and max-nr-of-instances-per-node = 2
# it will deploy 2 routees per new member in the cluster, up to # it will deploy 2 routees per new member in the cluster, up to
# 25 members. # 25 members.
max-nr-of-instances-per-node = 1 max-nr-of-instances-per-node = 1
# Maximum number of routees that will be deployed, in total
# on all nodes. See also description of max-nr-of-instances-per-node.
# For backwards compatibility reasons, nr-of-instances
# has the same purpose as max-total-nr-of-instances for cluster
# aware routers and nr-of-instances (if defined by user) takes
# precedence over max-total-nr-of-instances.
max-total-nr-of-instances = 10000
# Defines if routees are allowed to be located on the same node as # Defines if routees are allowed to be located on the same node as
# the head router actor, or only on remote nodes. # the head router actor, or only on remote nodes.

View file

@ -11,6 +11,7 @@ import akka.remote.{ RemoteActorRefProvider, RemoteDeployer }
import akka.remote.routing.RemoteRouterConfig import akka.remote.routing.RemoteRouterConfig
import akka.routing.{ Group, Pool } import akka.routing.{ Group, Pool }
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
/** /**
* INTERNAL API * INTERNAL API
@ -60,9 +61,19 @@ private[akka] class ClusterActorRefProvider(
* Deployer of cluster aware routers. * Deployer of cluster aware routers.
*/ */
private[akka] class ClusterDeployer(_settings: ActorSystem.Settings, _pm: DynamicAccess) extends RemoteDeployer(_settings, _pm) { private[akka] class ClusterDeployer(_settings: ActorSystem.Settings, _pm: DynamicAccess) extends RemoteDeployer(_settings, _pm) {
override def parseConfig(path: String, config: Config): Option[Deploy] = {
super.parseConfig(path, config) match { override def parseConfig(path: String, config: Config): Option[Deploy] = {
// config is the user supplied section, no defaults
// amend it to use max-total-nr-of-instances as nr-of-instances if cluster.enabled and
// user has not specified nr-of-instances
val config2 =
if (config.hasPath("cluster.enabled") && config.getBoolean("cluster.enabled") && !config.hasPath("nr-of-instances")) {
val maxTotalNrOfInstances = config.withFallback(default).getInt("cluster.max-total-nr-of-instances")
ConfigFactory.parseString("nr-of-instances=" + maxTotalNrOfInstances)
.withFallback(config)
} else config
super.parseConfig(path, config2) match {
case d @ Some(deploy) case d @ Some(deploy)
if (deploy.config.getBoolean("cluster.enabled")) { if (deploy.config.getBoolean("cluster.enabled")) {
if (deploy.scope != NoScopeGiven) if (deploy.scope != NoScopeGiven)

View file

@ -139,7 +139,7 @@ final case class AdaptiveLoadBalancingPool(
extends Pool { extends Pool {
def this(config: Config, dynamicAccess: DynamicAccess) = def this(config: Config, dynamicAccess: DynamicAccess) =
this(nrOfInstances = config.getInt("nr-of-instances"), this(nrOfInstances = ClusterRouterSettingsBase.getMaxTotalNrOfInstances(config),
metricsSelector = MetricsSelector.fromConfig(config, dynamicAccess), metricsSelector = MetricsSelector.fromConfig(config, dynamicAccess),
usePoolDispatcher = config.hasPath("pool-dispatcher")) usePoolDispatcher = config.hasPath("pool-dispatcher"))

View file

@ -32,7 +32,7 @@ import scala.collection.immutable
object ClusterRouterGroupSettings { object ClusterRouterGroupSettings {
def fromConfig(config: Config): ClusterRouterGroupSettings = def fromConfig(config: Config): ClusterRouterGroupSettings =
ClusterRouterGroupSettings( ClusterRouterGroupSettings(
totalInstances = config.getInt("nr-of-instances"), totalInstances = ClusterRouterSettingsBase.getMaxTotalNrOfInstances(config),
routeesPaths = immutableSeq(config.getStringList("routees.paths")), routeesPaths = immutableSeq(config.getStringList("routees.paths")),
allowLocalRoutees = config.getBoolean("cluster.allow-local-routees"), allowLocalRoutees = config.getBoolean("cluster.allow-local-routees"),
useRole = ClusterRouterSettingsBase.useRoleOption(config.getString("cluster.use-role"))) useRole = ClusterRouterSettingsBase.useRoleOption(config.getString("cluster.use-role")))
@ -69,7 +69,7 @@ final case class ClusterRouterGroupSettings(
object ClusterRouterPoolSettings { object ClusterRouterPoolSettings {
def fromConfig(config: Config): ClusterRouterPoolSettings = def fromConfig(config: Config): ClusterRouterPoolSettings =
ClusterRouterPoolSettings( ClusterRouterPoolSettings(
totalInstances = config.getInt("nr-of-instances"), totalInstances = ClusterRouterSettingsBase.getMaxTotalNrOfInstances(config),
maxInstancesPerNode = config.getInt("cluster.max-nr-of-instances-per-node"), maxInstancesPerNode = config.getInt("cluster.max-nr-of-instances-per-node"),
allowLocalRoutees = config.getBoolean("cluster.allow-local-routees"), allowLocalRoutees = config.getBoolean("cluster.allow-local-routees"),
useRole = ClusterRouterSettingsBase.useRoleOption(config.getString("cluster.use-role"))) useRole = ClusterRouterSettingsBase.useRoleOption(config.getString("cluster.use-role")))
@ -105,6 +105,18 @@ private[akka] object ClusterRouterSettingsBase {
case null | "" None case null | "" None
case _ Some(role) case _ Some(role)
} }
/**
* For backwards compatibility reasons, nr-of-instances
* has the same purpose as max-total-nr-of-instances for cluster
* aware routers and nr-of-instances (if defined by user) takes
* precedence over max-total-nr-of-instances.
*/
def getMaxTotalNrOfInstances(config: Config): Int =
config.getInt("nr-of-instances") match {
case 1 | 0 config.getInt("cluster.max-nr-of-instances-per-node")
case other other
}
} }
/** /**

View file

@ -141,7 +141,6 @@ private[cluster] object StressMultiJvmSpec extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/master-node-1/workers { /master-node-1/workers {
router = round-robin-pool router = round-robin-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 1 max-nr-of-instances-per-node = 1
@ -150,7 +149,6 @@ private[cluster] object StressMultiJvmSpec extends MultiNodeConfig {
} }
/master-node-2/workers { /master-node-2/workers {
router = round-robin-group router = round-robin-group
nr-of-instances = 100
routees.paths = ["/user/worker"] routees.paths = ["/user/worker"]
cluster { cluster {
enabled = on enabled = on
@ -159,7 +157,6 @@ private[cluster] object StressMultiJvmSpec extends MultiNodeConfig {
} }
/master-node-3/workers = { /master-node-3/workers = {
router = adaptive-pool router = adaptive-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 1 max-nr-of-instances-per-node = 1

View file

@ -70,10 +70,10 @@ object AdaptiveLoadBalancingRouterMultiJvmSpec extends MultiNodeConfig {
/router4 = { /router4 = {
router = adaptive-pool router = adaptive-pool
metrics-selector = "akka.cluster.routing.TestCustomMetricsSelector" metrics-selector = "akka.cluster.routing.TestCustomMetricsSelector"
nr-of-instances = 10
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 2 max-nr-of-instances-per-node = 2
max-total-nr-of-instances = 10
} }
} }
} }

View file

@ -40,10 +40,10 @@ object ClusterConsistentHashingRouterMultiJvmSpec extends MultiNodeConfig {
withFallback(ConfigFactory.parseString(s""" withFallback(ConfigFactory.parseString(s"""
common-router-settings = { common-router-settings = {
router = consistent-hashing-pool router = consistent-hashing-pool
nr-of-instances = 10
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 2 max-nr-of-instances-per-node = 2
max-total-nr-of-instances = 10
} }
} }

View file

@ -52,33 +52,33 @@ object ClusterRoundRobinMultiJvmSpec extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/router1 { /router1 {
router = round-robin-pool router = round-robin-pool
nr-of-instances = 10
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 2 max-nr-of-instances-per-node = 2
max-total-nr-of-instances = 10
} }
} }
/router3 { /router3 {
router = round-robin-pool router = round-robin-pool
nr-of-instances = 10
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 1 max-nr-of-instances-per-node = 1
max-total-nr-of-instances = 10
allow-local-routees = off allow-local-routees = off
} }
} }
/router4 { /router4 {
router = round-robin-group router = round-robin-group
nr-of-instances = 10
routees.paths = ["/user/myserviceA", "/user/myserviceB"] routees.paths = ["/user/myserviceA", "/user/myserviceB"]
cluster.enabled = on cluster.enabled = on
cluster.max-total-nr-of-instances = 10
} }
/router5 { /router5 {
router = round-robin-pool router = round-robin-pool
nr-of-instances = 10
cluster { cluster {
enabled = on enabled = on
use-role = a use-role = a
max-total-nr-of-instances = 10
} }
} }
} }

View file

@ -18,18 +18,18 @@ object ClusterDeployerSpec {
akka.actor.deployment { akka.actor.deployment {
/user/service1 { /user/service1 {
router = round-robin-pool router = round-robin-pool
nr-of-instances = 20
cluster.enabled = on cluster.enabled = on
cluster.max-nr-of-instances-per-node = 3 cluster.max-nr-of-instances-per-node = 3
cluster.max-total-nr-of-instances = 20
cluster.allow-local-routees = off cluster.allow-local-routees = off
} }
/user/service2 { /user/service2 {
dispatcher = mydispatcher dispatcher = mydispatcher
mailbox = mymailbox mailbox = mymailbox
router = round-robin-group router = round-robin-group
nr-of-instances = 20
routees.paths = ["/user/myservice"] routees.paths = ["/user/myservice"]
cluster.enabled = on cluster.enabled = on
cluster.max-total-nr-of-instances = 20
cluster.allow-local-routees = off cluster.allow-local-routees = off
} }
} }

View file

@ -467,8 +467,9 @@ actors to which the messages will be forwarded to by the router.
Messages will be forwarded to the routees using :ref:`ActorSelection <actorSelection-java>`, so the same delivery semantics should be expected. Messages will be forwarded to the routees using :ref:`ActorSelection <actorSelection-java>`, so the same delivery semantics should be expected.
It is possible to limit the lookup of routees to member nodes tagged with a certain role by specifying ``use-role``. It is possible to limit the lookup of routees to member nodes tagged with a certain role by specifying ``use-role``.
``nr-of-instances`` defines total number of routees in the cluster. Setting ``nr-of-instances`` ``max-total-nr-of-instances`` defines total number of routees in the cluster. By default ``max-total-nr-of-instances``
to a high value will result in new routees added to the router when nodes join the cluster. is set to a high value (10000) that will result in new routees added to the router when nodes join the cluster.
Set it to a lower value if you want to limit total number of routees.
The same type of router could also have been defined in code: The same type of router could also have been defined in code:
@ -528,10 +529,10 @@ the configuration for a router looks like this:
It is possible to limit the deployment of routees to member nodes tagged with a certain role by It is possible to limit the deployment of routees to member nodes tagged with a certain role by
specifying ``use-role``. specifying ``use-role``.
``nr-of-instances`` defines total number of routees in the cluster, but the number of routees ``max-total-nr-of-instances`` defines total number of routees in the cluster, but the number of routees
per node, ``max-nr-of-instances-per-node``, will not be exceeded. Setting ``nr-of-instances`` per node, ``max-nr-of-instances-per-node``, will not be exceeded. By default ``max-total-nr-of-instances``
to a high value will result in creating and deploying additional routees when new nodes join is set to a high value (10000) that will result in new routees added to the router when nodes join the cluster.
the cluster. Set it to a lower value if you want to limit total number of routees.
The same type of router could also have been defined in code: The same type of router could also have been defined in code:

View file

@ -155,6 +155,21 @@ In order to make cluster routers smarter about when they can start local routees
In case you have implemented a custom Group you will have to update the method's signature, In case you have implemented a custom Group you will have to update the method's signature,
however the implementation can remain the same if you don't need to rely on an ActorSystem in your logic. however the implementation can remain the same if you don't need to rely on an ActorSystem in your logic.
Cluster aware router max-total-nr-of-instances
==============================================
In 2.3.x the deployment configuration property ``nr-of-instances`` was used for
cluster aware routers to specify total number of routees in the cluster.
This was confusing, especially since the default value is 1.
In 2.4.x there is a new deployement property ``cluster.max-total-nr-of-instances`` that
defines total number of routees in the cluster. By default ``max-total-nr-of-instances``
is set to a high value (10000) that will result in new routees added to the router when nodes join the cluster.
Set it to a lower value if you want to limit total number of routees.
For backwards compatibility reasons ``nr-of-instances`` is still used if defined by user,
i.e. if defined it takes precedence over ``max-total-nr-of-instances``.
Logger names use full class name Logger names use full class name
================================ ================================
Previously, few places in akka used "simple" logger names, such as ``Cluster`` or ``Remoting``. Previously, few places in akka used "simple" logger names, such as ``Cluster`` or ``Remoting``.

View file

@ -464,8 +464,9 @@ actors to which the messages will be forwarded to by the router.
Messages will be forwarded to the routees using :ref:`ActorSelection <actorSelection-scala>`, so the same delivery semantics should be expected. Messages will be forwarded to the routees using :ref:`ActorSelection <actorSelection-scala>`, so the same delivery semantics should be expected.
It is possible to limit the lookup of routees to member nodes tagged with a certain role by specifying ``use-role``. It is possible to limit the lookup of routees to member nodes tagged with a certain role by specifying ``use-role``.
``nr-of-instances`` defines total number of routees in the cluster. Setting ``nr-of-instances`` ``max-total-nr-of-instances`` defines total number of routees in the cluster. By default ``max-total-nr-of-instances``
to a high value will result in new routees added to the router when nodes join the cluster. is set to a high value (10000) that will result in new routees added to the router when nodes join the cluster.
Set it to a lower value if you want to limit total number of routees.
The same type of router could also have been defined in code: The same type of router could also have been defined in code:
@ -523,10 +524,10 @@ the configuration for a router looks like this:
It is possible to limit the deployment of routees to member nodes tagged with a certain role by It is possible to limit the deployment of routees to member nodes tagged with a certain role by
specifying ``use-role``. specifying ``use-role``.
``nr-of-instances`` defines total number of routees in the cluster, but the number of routees ``max-total-nr-of-instances`` defines total number of routees in the cluster, but the number of routees
per node, ``max-nr-of-instances-per-node``, will not be exceeded. Setting ``nr-of-instances`` per node, ``max-nr-of-instances-per-node``, will not be exceeded. By default ``max-total-nr-of-instances``
to a high value will result in creating and deploying additional routees when new nodes join is set to a high value (10000) that will result in new routees added to the router when nodes join the cluster.
the cluster. Set it to a lower value if you want to limit total number of routees.
The same type of router could also have been defined in code: The same type of router could also have been defined in code:

View file

@ -22,7 +22,6 @@ akka.actor.deployment {
# metrics-selector = cpu # metrics-selector = cpu
metrics-selector = mix metrics-selector = mix
# #
nr-of-instances = 100
routees.paths = ["/user/factorialBackend"] routees.paths = ["/user/factorialBackend"]
cluster { cluster {
enabled = on enabled = on

View file

@ -4,7 +4,6 @@ include "application"
akka.actor.deployment { akka.actor.deployment {
/statsService/workerRouter { /statsService/workerRouter {
router = consistent-hashing-group router = consistent-hashing-group
nr-of-instances = 100
routees.paths = ["/user/statsWorker"] routees.paths = ["/user/statsWorker"]
cluster { cluster {
enabled = on enabled = on

View file

@ -4,7 +4,6 @@ include "application"
akka.actor.deployment { akka.actor.deployment {
/statsService/singleton/workerRouter { /statsService/singleton/workerRouter {
router = consistent-hashing-pool router = consistent-hashing-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 3 max-nr-of-instances-per-node = 3

View file

@ -56,7 +56,6 @@ object StatsSampleSingleMasterSpecConfig extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/statsService/singleton/workerRouter { /statsService/singleton/workerRouter {
router = consistent-hashing-pool router = consistent-hashing-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 3 max-nr-of-instances-per-node = 3

View file

@ -51,7 +51,6 @@ object StatsSampleSpecConfig extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/statsService/workerRouter { /statsService/workerRouter {
router = consistent-hashing-group router = consistent-hashing-group
nr-of-instances = 100
routees.paths = ["/user/statsWorker"] routees.paths = ["/user/statsWorker"]
cluster { cluster {
enabled = on enabled = on

View file

@ -22,7 +22,6 @@ akka.actor.deployment {
# metrics-selector = cpu # metrics-selector = cpu
metrics-selector = mix metrics-selector = mix
# #
nr-of-instances = 100
routees.paths = ["/user/factorialBackend"] routees.paths = ["/user/factorialBackend"]
cluster { cluster {
enabled = on enabled = on

View file

@ -4,7 +4,6 @@ include "application"
akka.actor.deployment { akka.actor.deployment {
/statsService/workerRouter { /statsService/workerRouter {
router = consistent-hashing-group router = consistent-hashing-group
nr-of-instances = 100
routees.paths = ["/user/statsWorker"] routees.paths = ["/user/statsWorker"]
cluster { cluster {
enabled = on enabled = on

View file

@ -4,7 +4,6 @@ include "application"
akka.actor.deployment { akka.actor.deployment {
/statsService/singleton/workerRouter { /statsService/singleton/workerRouter {
router = consistent-hashing-pool router = consistent-hashing-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 3 max-nr-of-instances-per-node = 3

View file

@ -55,7 +55,6 @@ object StatsSampleSingleMasterSpecConfig extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/statsService/singleton/workerRouter { /statsService/singleton/workerRouter {
router = consistent-hashing-pool router = consistent-hashing-pool
nr-of-instances = 100
cluster { cluster {
enabled = on enabled = on
max-nr-of-instances-per-node = 3 max-nr-of-instances-per-node = 3

View file

@ -47,7 +47,6 @@ object StatsSampleSpecConfig extends MultiNodeConfig {
akka.actor.deployment { akka.actor.deployment {
/statsService/workerRouter { /statsService/workerRouter {
router = consistent-hashing-group router = consistent-hashing-group
nr-of-instances = 100
routees.paths = ["/user/statsWorker"] routees.paths = ["/user/statsWorker"]
cluster { cluster {
enabled = on enabled = on