Merge pull request #1918 from akka/wip-2927-balancing-pool-patriknw

!act #2927 Add BalancingPool and deprecate BalancingDispatcher
This commit is contained in:
Patrik Nordwall 2014-01-16 12:30:26 -08:00
commit 32b76adb9a
26 changed files with 482 additions and 206 deletions

View file

@ -114,17 +114,6 @@ object DispatcherDocSpec {
}
//#my-bounded-config
//#my-balancing-config
my-balancing-dispatcher {
type = BalancingDispatcher
executor = "thread-pool-executor"
thread-pool-executor {
core-pool-size-factor = 8.0
max-pool-size-factor = 16.0
}
}
//#my-balancing-config
//#prio-dispatcher-config
prio-dispatcher {
mailbox-type = "docs.dispatcher.DispatcherDocSpec$MyPrioMailbox"
@ -342,10 +331,6 @@ class DispatcherDocSpec extends AkkaSpec(DispatcherDocSpec.config) {
}
}
"defining balancing dispatcher" in {
val dispatcher = system.dispatchers.lookup("my-balancing-dispatcher")
}
"require custom mailbox on dispatcher" in {
val myActor = system.actorOf(Props[MyActor].withDispatcher(
"custom-dispatcher"))

View file

@ -20,6 +20,7 @@ import akka.routing.DefaultResizer
import akka.routing.ScatterGatherFirstCompletedGroup
import akka.routing.RandomGroup
import akka.routing.ScatterGatherFirstCompletedPool
import akka.routing.BalancingPool
object RouterDocSpec {
@ -59,10 +60,31 @@ akka.actor.deployment {
}
}
#//#config-random-group
#//#config-balancing-pool
akka.actor.deployment {
/parent/router9 {
router = balancing-pool
nr-of-instances = 5
}
}
#//#config-balancing-pool
#//#config-balancing-pool2
akka.actor.deployment {
/parent/router9b {
router = balancing-pool
nr-of-instances = 5
pool-dispatcher {
attempt-teamwork = off
}
}
}
#//#config-balancing-pool2
#//#config-smallest-mailbox-pool
akka.actor.deployment {
/parent/router9 {
/parent/router11 {
router = smallest-mailbox-pool
nr-of-instances = 5
}
@ -71,7 +93,7 @@ akka.actor.deployment {
#//#config-broadcast-pool
akka.actor.deployment {
/parent/router11 {
/parent/router13 {
router = broadcast-pool
nr-of-instances = 5
}
@ -80,7 +102,7 @@ akka.actor.deployment {
#//#config-broadcast-group
akka.actor.deployment {
/parent/router13 {
/parent/router15 {
router = broadcast-group
routees.paths = ["/user/workers/w1", "/user/workers/w2", "/user/workers/w3"]
}
@ -89,7 +111,7 @@ akka.actor.deployment {
#//#config-scatter-gather-pool
akka.actor.deployment {
/parent/router15 {
/parent/router17 {
router = scatter-gather-pool
nr-of-instances = 5
within = 10 seconds
@ -99,7 +121,7 @@ akka.actor.deployment {
#//#config-scatter-gather-group
akka.actor.deployment {
/parent/router17 {
/parent/router19 {
router = scatter-gather-group
routees.paths = ["/user/workers/w1", "/user/workers/w2", "/user/workers/w3"]
within = 10 seconds
@ -109,7 +131,7 @@ akka.actor.deployment {
#//#config-consistent-hashing-pool
akka.actor.deployment {
/parent/router19 {
/parent/router21 {
router = consistent-hashing-pool
nr-of-instances = 5
virtual-nodes-factor = 10
@ -119,7 +141,7 @@ akka.actor.deployment {
#//#config-consistent-hashing-group
akka.actor.deployment {
/parent/router21 {
/parent/router23 {
router = consistent-hashing-group
routees.paths = ["/user/workers/w1", "/user/workers/w2", "/user/workers/w3"]
virtual-nodes-factor = 10
@ -129,7 +151,7 @@ akka.actor.deployment {
#//#config-resize-pool
akka.actor.deployment {
/parent/router23 {
/parent/router25 {
router = round-robin-pool
resizer {
lower-bound = 2
@ -146,7 +168,8 @@ akka.actor.deployment {
router = random-pool
nr-of-instances = 5
pool-dispatcher {
type = BalancingDispatcher
fork-join-executor.parallelism-min = 5
fork-join-executor.parallelism-max = 5
}
}
}
@ -249,89 +272,99 @@ router-dispatcher {}
context.actorOf(RandomGroup(paths).props(), "router8")
//#random-group-2
//#smallest-mailbox-pool-1
//#balancing-pool-1
val router9: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router9")
//#balancing-pool-1
//#balancing-pool-2
val router10: ActorRef =
context.actorOf(BalancingPool(5).props(Props[Worker]), "router10")
//#balancing-pool-2
//#smallest-mailbox-pool-1
val router11: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router11")
//#smallest-mailbox-pool-1
//#smallest-mailbox-pool-2
val router10: ActorRef =
context.actorOf(SmallestMailboxPool(5).props(Props[Worker]), "router10")
val router12: ActorRef =
context.actorOf(SmallestMailboxPool(5).props(Props[Worker]), "router12")
//#smallest-mailbox-pool-2
//#broadcast-pool-1
val router11: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router11")
val router13: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router13")
//#broadcast-pool-1
//#broadcast-pool-2
val router12: ActorRef =
context.actorOf(BroadcastPool(5).props(Props[Worker]), "router12")
val router14: ActorRef =
context.actorOf(BroadcastPool(5).props(Props[Worker]), "router14")
//#broadcast-pool-2
//#broadcast-group-1
val router13: ActorRef =
context.actorOf(FromConfig.props(), "router13")
val router15: ActorRef =
context.actorOf(FromConfig.props(), "router15")
//#broadcast-group-1
//#broadcast-group-2
val router14: ActorRef =
context.actorOf(BroadcastGroup(paths).props(), "router14")
val router16: ActorRef =
context.actorOf(BroadcastGroup(paths).props(), "router16")
//#broadcast-group-2
//#scatter-gather-pool-1
val router15: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router15")
val router17: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router17")
//#scatter-gather-pool-1
//#scatter-gather-pool-2
val router16: ActorRef =
val router18: ActorRef =
context.actorOf(ScatterGatherFirstCompletedPool(5, within = 10.seconds).
props(Props[Worker]), "router16")
props(Props[Worker]), "router18")
//#scatter-gather-pool-2
//#scatter-gather-group-1
val router17: ActorRef =
context.actorOf(FromConfig.props(), "router17")
val router19: ActorRef =
context.actorOf(FromConfig.props(), "router19")
//#scatter-gather-group-1
//#scatter-gather-group-2
val router18: ActorRef =
val router20: ActorRef =
context.actorOf(ScatterGatherFirstCompletedGroup(paths,
within = 10.seconds).props(), "router18")
within = 10.seconds).props(), "router20")
//#scatter-gather-group-2
//#consistent-hashing-pool-1
val router19: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router19")
val router21: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router21")
//#consistent-hashing-pool-1
//#consistent-hashing-pool-2
val router20: ActorRef =
val router22: ActorRef =
context.actorOf(ConsistentHashingPool(5).props(Props[Worker]),
"router20")
"router22")
//#consistent-hashing-pool-2
//#consistent-hashing-group-1
val router21: ActorRef =
context.actorOf(FromConfig.props(), "router21")
val router23: ActorRef =
context.actorOf(FromConfig.props(), "router23")
//#consistent-hashing-group-1
//#consistent-hashing-group-2
val router22: ActorRef =
context.actorOf(ConsistentHashingGroup(paths).props(), "router22")
val router24: ActorRef =
context.actorOf(ConsistentHashingGroup(paths).props(), "router24")
//#consistent-hashing-group-2
//#resize-pool-1
val router23: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router23")
val router25: ActorRef =
context.actorOf(FromConfig.props(Props[Worker]), "router25")
//#resize-pool-1
//#resize-pool-2
val resizer = DefaultResizer(lowerBound = 2, upperBound = 15)
val router24: ActorRef =
val router26: ActorRef =
context.actorOf(RoundRobinPool(5, Some(resizer)).props(Props[Worker]),
"router24")
"router26")
//#resize-pool-2
def receive = {

View file

@ -4,8 +4,8 @@ Mailboxes
#########
An Akka ``Mailbox`` holds the messages that are destined for an ``Actor``.
Normally each ``Actor`` has its own mailbox, but with for example a ``BalancingDispatcher``
all actors with the same ``BalancingDispatcher`` will share a single instance.
Normally each ``Actor`` has its own mailbox, but with for example a ``BalancingPool``
all routees will share a single mailbox instance.
Mailbox Selection
=================

View file

@ -251,6 +251,31 @@ RandomGroup defined in code:
.. includecode:: code/docs/routing/RouterDocSpec.scala
:include: paths,random-group-2
.. _balancing-pool-scala:
BalancingPool
-------------
A Router that will try to redistribute work from busy routees to idle routees.
All routees share the same mailbox.
BalancingPool defined in configuration:
.. includecode:: code/docs/routing/RouterDocSpec.scala#config-balancing-pool
.. includecode:: code/docs/routing/RouterDocSpec.scala#balancing-pool-1
BalancingPool defined in code:
.. includecode:: code/docs/routing/RouterDocSpec.scala#balancing-pool-2
Addition configuration for the balancing dispatcher, which is used by the pool,
can be configured in the ``pool-dispatcher`` section of the router deployment
configuration.
.. includecode:: code/docs/routing/RouterDocSpec.scala#config-balancing-pool2
There is no Group variant of the BalancingPool.
SmallestMailboxPool
-------------------
@ -515,7 +540,7 @@ and when you receive the ``Routees`` reply you know that the preceeding change h
Dynamically Resizable Pool
^^^^^^^^^^^^^^^^^^^^^^^^^^
All pools can be used with a fixed number of routees or with a resize strategy to adjust the number
Most pools can be used with a fixed number of routees or with a resize strategy to adjust the number
of routees dynamically.
Pool with resizer defined in configuration:
@ -627,11 +652,7 @@ Configuring Dispatchers
^^^^^^^^^^^^^^^^^^^^^^^
The dispatcher for created children of the pool will be taken from
``Props`` as described in :ref:`dispatchers-scala`. For a pool it
makes sense to configure the ``BalancingDispatcher`` if the precise
routing is not so important (i.e. no consistent hashing or round-robin is
required); this enables newly created routees to pick up work immediately by
stealing it from their siblings.
``Props`` as described in :ref:`dispatchers-scala`.
To make it easy to define the dispatcher of the routees of the pool you can
define the dispatcher inline in the deployment section of the config.
@ -660,28 +681,5 @@ implement the method in a suitable way.
.. note::
It is not allowed to configure the ``routerDispatcher`` to be a
:class:`BalancingDispatcher` since the messages meant for the special
router actor cannot be processed by any other actor.
At first glance there seems to be an overlap between the
:class:`BalancingDispatcher` and Routers, but they complement each other.
The balancing dispatcher is in charge of running the actors while the routers
are in charge of deciding which message goes where. A router can also have
children that span multiple actor systems, even remote ones, but a dispatcher
lives inside a single actor system.
When using a :class:`RoundRobinRouter` with a :class:`BalancingDispatcher`
there are some configuration settings to take into account.
- There can only be ``nr-of-instances`` messages being processed at the same
time no matter how many threads are configured for the
:class:`BalancingDispatcher`.
- Having ``throughput`` set to a low number makes no sense since you will only
be handing off to another actor that processes the same :class:`MailBox`
as yourself, which can be costly. Either the message just got into the
mailbox and you can receive it as well as anybody else, or everybody else
is busy and you are the only one available to receive the message.
- Resizing the number of routees only introduce inertia, since resizing
is performed at specified intervals, but work stealing is instantaneous.
:class:`akka.dispatch.BalancingDispatcherConfigurator` since the messages meant
for the special router actor cannot be processed by any other actor.