+act #18356 Metrics based resizer for router

This commit is contained in:
Kailuo Wang 2015-08-21 21:03:57 -04:00
parent fb80ac8acb
commit 90cba9ce0d
19 changed files with 904 additions and 17 deletions

View file

@ -593,7 +593,16 @@ Dynamically Resizable Pool
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:
There are two types of resizers: the default ``Resizer`` and the ``OptimalSizeExploringResizer``.
Default Resizer
---------------
The default resizer ramps up and down pool size based on pressure, measured by the percentage of busy routees
in the pool. It ramps up pool size if the pressure is higher than a certain threshold and backs off if the
pressure is lower than certain threshold. Both thresholds are configurable.
Pool with default resizer defined in configuration:
.. includecode:: code/docs/routing/RouterDocSpec.scala#config-resize-pool
@ -609,6 +618,43 @@ Pool with resizer defined in code:
*It is also worth pointing out that if you define the ``router`` in the configuration file then this value
will be used instead of any programmatically sent parameters.*
Optimal Size Exploring Resizer
------------------------------
The ``OptimalSizeExploringResizer`` resizes the pool to an optimal size that provides the most message throughput.
This resizer works best when you expect the pool size to performance function to be a convex function.
For example, when you have a CPU bound tasks, the optimal size is bound to the number of CPU cores.
When your task is IO bound, the optimal size is bound to optimal number of concurrent connections to that IO service -
e.g. a 4 node elastic search cluster may handle 4-8 concurrent requests at optimal speed.
It achieves this by keeping track of message throughput at each pool size and performing the following
three resizing operations (one at a time) periodically:
* Downsize if it hasn't seen all routees ever fully utilized for a period of time.
* Explore to a random nearby pool size to try and collect throughput metrics.
* Optimize to a nearby pool size with a better (than any other nearby sizes) throughput metrics.
When the pool is fully-utilized (i.e. all routees are busy), it randomly choose between exploring and optimizing.
When the pool has not been fully-utilized for a period of time, it will downsize the pool to the last seen max
utilization multiplied by a configurable ratio.
By constantly exploring and optimizing, the resizer will eventually walk to the optimal size and
remain nearby. When the optimal size changes it will start walking towards the new one.
It keeps a performance log so it's stateful as well as having a larger memory footprint than the default ``Resizer``.
The memory usage is O(n) where n is the number of sizes you allow, i.e. upperBound - lowerBound.
Pool with ``OptimalSizeExploringResizer`` defined in configuration:
.. includecode:: code/docs/routing/RouterDocSpec.scala#config-optimal-size-exploring-resize-pool
.. includecode:: code/docs/routing/RouterDocSpec.scala#optimal-size-exploring-resize-pool
Several more configuration options are available and described in ``akka.actor.deployment.default.optimal-size-exploring-resizer``
section of the reference :ref:`configuration`.
.. note::
Resizing is triggered by sending messages to the actor pool, but it is not
@ -619,6 +665,7 @@ will be used instead of any programmatically sent parameters.*
this, configure the pool to use a balancing dispatcher, see `Configuring
Dispatchers`_ for more information.
.. _router-design-scala:
How Routing is Designed within Akka