class
TimerBasedThrottler extends Actor with FSM[State, Data]
Instance Constructors
-
new
TimerBasedThrottler(rate: Rate)
Type Members
-
type
Event = actor.FSM.Event[Data]
-
-
type
State = actor.FSM.State[TimerBasedThrottler.State, Data]
-
-
type
StopEvent = actor.FSM.StopEvent[TimerBasedThrottler.State, Data]
-
-
final
class
TransformHelper extends AnyRef
-
type
TransitionHandler = PartialFunction[(TimerBasedThrottler.State, TimerBasedThrottler.State), Unit]
Value Members
-
final
def
!=(arg0: Any): Boolean
-
final
def
##(): Int
-
def
+(other: String): String
-
val
->: actor.FSM.->.type
-
final
def
==(arg0: Any): Boolean
-
val
Event: actor.FSM.Event.type
-
val
StateTimeout: actor.FSM.StateTimeout.type
-
val
StopEvent: actor.FSM.StopEvent.type
-
def
aroundPostRestart(reason: Throwable): Unit
-
def
aroundPostStop(): Unit
-
def
aroundPreRestart(reason: Throwable, message: Option[Any]): Unit
-
def
aroundPreStart(): Unit
-
def
aroundReceive(receive: actor.Actor.Receive, msg: Any): Unit
-
final
def
asInstanceOf[T0]: T0
-
final
def
cancelTimer(name: String): Unit
-
def
clone(): AnyRef
-
-
-
-
-
-
final
def
eq(arg0: AnyRef): Boolean
-
def
equals(arg0: Any): Boolean
-
def
finalize(): Unit
-
def
formatted(fmtstr: String): String
-
final
def
getClass(): Class[_]
-
def
gossip(msg: Any)(implicit sender: ActorRef): Unit
-
final
def
goto(nextStateName: TimerBasedThrottler.State): State
-
def
hashCode(): Int
-
final
def
initialize(): Unit
-
final
def
isInstanceOf[T0]: Boolean
-
final
def
isTimerActive(name: String): Boolean
-
def
listenerManagement: actor.Actor.Receive
-
val
listeners: Set[ActorRef]
-
-
def
logTermination(reason: Reason): Unit
-
final
def
ne(arg0: AnyRef): Boolean
-
final
def
nextStateData: Data
-
final
def
notify(): Unit
-
final
def
notifyAll(): Unit
-
-
final
def
onTransition(transitionHandler: TransitionHandler): Unit
-
def
postRestart(reason: Throwable): Unit
-
def
postStop(): Unit
-
def
preRestart(reason: Throwable, message: Option[Any]): Unit
-
def
preStart(): Unit
-
var
rate: Rate
-
-
implicit final
val
self: ActorRef
-
final
def
sender(): ActorRef
-
final
def
setStateTimeout(state: TimerBasedThrottler.State, timeout: Timeout): Unit
-
final
def
setTimer(name: String, msg: Any, timeout: FiniteDuration, repeat: Boolean): Unit
-
final
def
startWith(stateName: TimerBasedThrottler.State, stateData: Data, timeout: Timeout): Unit
-
final
def
stateData: Data
-
final
def
stateName: TimerBasedThrottler.State
-
final
def
stay(): State
-
final
def
stop(reason: Reason, stateData: Data): State
-
final
def
stop(reason: Reason): State
-
final
def
stop(): State
-
def
supervisorStrategy: SupervisorStrategy
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
-
def
toString(): String
-
implicit final
def
total2pf(transitionHandler: (TimerBasedThrottler.State, TimerBasedThrottler.State) ⇒ Unit): TransitionHandler
-
-
def
unhandled(message: Any): Unit
-
final
def
wait(): Unit
-
final
def
wait(arg0: Long, arg1: Int): Unit
-
final
def
wait(arg0: Long): Unit
-
final
def
when(stateName: TimerBasedThrottler.State, stateTimeout: FiniteDuration)(stateFunction: StateFunction): Unit
-
final
def
whenUnhandled(stateFunction: StateFunction): Unit
-
Shadowed Implicit Value Members
-
Inherited from FSM[TimerBasedThrottler.State, Data]
Inherited from AnyRef
Inherited from Any
A throttler that uses a timer to control the message delivery rate.
Throttling
A throttler is an actor that is defined through a target actor and a rate (of type akka.contrib.throttle.Throttler.Rate). You set or change the target and rate at any time through the akka.contrib.throttle.Throttler.SetTarget and akka.contrib.throttle.Throttler.SetRate messages, respectively. When you send the throttler any other message
msg
, it will put the messagemsg
into an internal queue and eventually send all queued messages to the target, at a speed that respects the given rate. If no target is currently defined then the messages will be queued and will be delivered as soon as a target gets set.A throttler understands actor messages of type akka.contrib.throttle.Throttler.SetTarget, akka.contrib.throttle.Throttler.SetRate, in addition to any other messages, which the throttler will consider as messages to be sent to the target.
Transparency
Notice that the throttler
forward
s messages, i.e., the target will see the original message sender (and not the throttler) as the sender of the message.Persistence
Throttlers usually use an internal queue to keep the messages that need to be sent to the target. You therefore cannot rely on the throttler's inbox size in order to learn how much messages are outstanding.
It is left to the implementation whether the internal queue is persisted over application restarts or actor failure.
Processing messages
The target should process messages as fast as possible. If the target requires substantial time to process messages, it should distribute its work to other actors (using for example something like a
BalancingDispatcher
), otherwise the resulting system will always work below the threshold rate.Example: Suppose the throttler has a rate of 3msg/s and the target requires 1s to process a message. This system will only process messages at a rate of 1msg/s: the target will receive messages at at most 3msg/s but as it handles them synchronously and each of them takes 1s, its inbox will grow and grow. In such a situation, the target should distribute its messages to a set of worker actors so that individual messages can be handled in parallel.
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.(Since version 2.5.0) Use streams, see migration guide
akka.contrib.throttle.Throttler