For example, if you set a rate like "3 messages in 1 second", the throttler
will send the first three messages immediately to the target actor but will need to impose a delay before
sending out further messages:
// A simple actor that prints whatever it receivesval printer = system.actorOf(Props(new Actor {
def receive = {
case x => println(x)
}
}))
// The throttler for this example, setting the rateval throttler = system.actorOf(Props(new TimerBasedThrottler(3 msgsPer (1.second))))
// Set the target
throttler ! SetTarget(Some(printer))
// These three messages will be sent to the printer immediately
throttler ! "1"
throttler ! "2"
throttler ! "3"// These two will wait at least until 1 second has passed
throttler ! "4"
throttler ! "5"
Implementation notes
This throttler implementation internally installs a timer that repeats every rate.durationInMillis and enables rate.numberOfCalls
additional calls to take place. A TimerBasedThrottler uses very few system resources, provided the rate's duration is not too
fine-grained (which would cause a lot of timer invocations); for example, it does not store the calling history
as other throttlers may need to do.
However, a TimerBasedThrottler only provides weak guarantees on the rate (see also
this blog post):
Only delivery times are taken into account: if, for example, the throttler is used to throttle
requests to an external web service then only the start times of the web requests are considered.
If a web request takes very long on the server then more than rate.numberOfCalls-many requests
may be observed on the server in an interval of duration rate.durationInMillis().
There may be intervals of duration rate.durationInMillis() that contain more than rate.numberOfCalls
message deliveries: a TimerBasedThrottler only makes guarantees for the intervals
of its own timer, namely that no more than rate.numberOfCalls-many messages are delivered within such intervals. Other intervals on the
timeline may contain more calls.
For some applications, these guarantees may not be sufficient.
Known issues
If you change the rate using SetRate(rate), the actual rate may in fact be higher for the
overlapping period (i.e., durationInMillis()) of the new and old rate. Therefore,
changing the rate frequently is not recommended with the current implementation.
The queue of messages to be delivered is not persisted in any way; actor or system failure will
cause the queued messages to be lost.
A akka.contrib.throttle.Throttler that uses a timer to control the message delivery rate.
Example
For example, if you set a rate like "3 messages in 1 second", the throttler will send the first three messages immediately to the target actor but will need to impose a delay before sending out further messages:
Implementation notes
This throttler implementation internally installs a timer that repeats every
rate.durationInMillis
and enablesrate.numberOfCalls
additional calls to take place. ATimerBasedThrottler
uses very few system resources, provided the rate's duration is not too fine-grained (which would cause a lot of timer invocations); for example, it does not store the calling history as other throttlers may need to do.However, a
TimerBasedThrottler
only provides weak guarantees on the rate (see also this blog post):rate.numberOfCalls
-many requests may be observed on the server in an interval of durationrate.durationInMillis()
.rate.durationInMillis()
that contain more thanrate.numberOfCalls
message deliveries: aTimerBasedThrottler
only makes guarantees for the intervals of its own timer, namely that no more thanrate.numberOfCalls
-many messages are delivered within such intervals. Other intervals on the timeline may contain more calls.For some applications, these guarantees may not be sufficient.
Known issues
SetRate(rate)
, the actual rate may in fact be higher for the overlapping period (i.e.,durationInMillis()
) of the new and old rate. Therefore, changing the rate frequently is not recommended with the current implementation.akka.contrib.throttle.Throttler