2012-10-31 13:17:59 +01:00
|
|
|
|
Throttling Actor Messages
|
|
|
|
|
|
=========================
|
|
|
|
|
|
|
|
|
|
|
|
Introduction
|
|
|
|
|
|
------------
|
|
|
|
|
|
|
|
|
|
|
|
Suppose you are writing an application that makes HTTP requests to an external
|
|
|
|
|
|
web service and that this web service has a restriction in place: you may not
|
|
|
|
|
|
make more than 10 requests in 1 minute. You will get blocked or need to pay if
|
|
|
|
|
|
you don’t stay under this limit. In such a scenario you will want to employ
|
|
|
|
|
|
a *message throttler*.
|
|
|
|
|
|
|
|
|
|
|
|
This extension module provides a simple implementation of a throttling actor,
|
|
|
|
|
|
the :class:`TimerBasedThrottler`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
How to use it
|
|
|
|
|
|
-------------
|
|
|
|
|
|
|
2013-07-04 16:24:48 +02:00
|
|
|
|
You can use a :class:`TimerBasedThrottler` as follows. From Java it looks
|
|
|
|
|
|
like this:
|
|
|
|
|
|
|
|
|
|
|
|
.. includecode:: @contribSrc@/src/test/java/akka/contrib/throttle/TimerBasedThrottlerTest.java#demo-code
|
|
|
|
|
|
|
|
|
|
|
|
And from Scala like this:
|
2012-10-31 13:17:59 +01:00
|
|
|
|
|
|
|
|
|
|
.. includecode:: @contribSrc@/src/test/scala/akka/contrib/throttle/TimerBasedThrottlerSpec.scala#demo-code
|
|
|
|
|
|
|
2013-07-04 16:24:48 +02:00
|
|
|
|
Please refer to the JavaDoc/ScalaDoc documentation for the details.
|
2012-10-31 13:17:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The guarantees
|
|
|
|
|
|
--------------
|
|
|
|
|
|
|
|
|
|
|
|
:class:`TimerBasedThrottler` uses a timer internally. When the throttler’s rate is 3 msg/s,
|
|
|
|
|
|
for example, the throttler will start a timer that triggers
|
|
|
|
|
|
every second and each time will give the throttler exactly three "vouchers";
|
|
|
|
|
|
each voucher gives the throttler a right to deliver a message. In this way,
|
|
|
|
|
|
at most 3 messages will be sent out by the throttler in each interval.
|
|
|
|
|
|
|
|
|
|
|
|
It should be noted that such timer-based throttlers provide relatively **weak guarantees**:
|
|
|
|
|
|
|
|
|
|
|
|
* Only *start times* are taken into account. This may be a problem if, for example, the
|
|
|
|
|
|
throttler is used to throttle requests to an external web service. If a web request
|
|
|
|
|
|
takes very long on the server then the rate *observed on the server* may be higher.
|
|
|
|
|
|
* A timer-based throttler only makes guarantees for the intervals of its own timer. In
|
|
|
|
|
|
our example, no more than 3 messages are delivered within such intervals. Other
|
|
|
|
|
|
intervals on the timeline, however, may contain more calls.
|
|
|
|
|
|
|
|
|
|
|
|
The two cases are illustrated in the two figures below, each showing a timeline and three
|
|
|
|
|
|
intervals of the timer. The message delivery times chosen by the throttler are indicated
|
|
|
|
|
|
by dots, and as you can see, each interval contains at most 3 point, so the throttler
|
|
|
|
|
|
works correctly. Still, there is in each example an interval (the red one) that is
|
|
|
|
|
|
problematic. In the first scenario, this is because the delivery times are merely the
|
|
|
|
|
|
start times of longer requests (indicated by the four bars above the timeline that start
|
|
|
|
|
|
at the dots), so that the server observes four requests during the red interval. In the
|
|
|
|
|
|
second scenario, the messages are centered around one of the points in time where the
|
|
|
|
|
|
timer triggers, causing the red interval to contain too many messages.
|
|
|
|
|
|
|
|
|
|
|
|
.. image:: throttler.png
|
|
|
|
|
|
|
|
|
|
|
|
For some application scenarios, the guarantees provided by a timer-based throttler might
|
|
|
|
|
|
be too weak. Charles Cordingley’s `blog post <http://www.cordinc.com/blog/2010/04/java-multichannel-asynchronous.html>`_
|
|
|
|
|
|
discusses a throttler with stronger guarantees (it solves problem 2 from above).
|
|
|
|
|
|
Future versions of this module may feature throttlers with better guarantees.
|