|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objectcom.google.common.util.concurrent.RateLimiter
@ThreadSafe @Beta public abstract class RateLimiter
A rate limiter. Conceptually, a rate limiter distributes permits at a
configurable rate. Each acquire() blocks if necessary until a permit is
available, and then takes it. Once acquired, permits need not be released.
Rate limiters are often used to restrict the rate at which some
physical or logical resource is accessed. This is in contrast to Semaphore which restricts the number of concurrent
accesses instead of the rate (note though that concurrency and rate are closely related,
e.g. see Little's Law).
A RateLimiter is defined primarily by the rate at which permits
are issued. Absent additional configuration, permits will be distributed at a
fixed rate, defined in terms of permits per second. Permits will be distributed
smoothly, with the delay between individual permits being adjusted to ensure
that the configured rate is maintained.
It is possible to configure a RateLimiter to have a warmup
period during which time the permits issued each second steadily increases until
it hits the stable rate.
As an example, imagine that we have a list of tasks to execute, but we don't want to submit more than 2 per second:
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second"
void submitTasks(List<Runnable> tasks, Executor executor) {
for (Runnable task : tasks) {
rateLimiter.acquire(); // may wait
executor.execute(task);
}
}
As another example, imagine that we produce a stream of data, and we want to cap it at 5kb per second. This could be accomplished by requiring a permit per byte, and specifying a rate of 5000 permits per second:
final RateLimiter rateLimiter = RateLimiter.create(5000.0); // rate = 5000 permits per second
void submitPacket(byte[] packet) {
rateLimiter.acquire(packet.length);
networkService.send(packet);
}
It is important to note that the number of permits requested never
affect the throttling of the request itself (an invocation to acquire(1)
and an invocation to acquire(1000) will result in exactly the same throttling, if any),
but it affects the throttling of the next request. I.e., if an expensive task
arrives at an idle RateLimiter, it will be granted immediately, but it is the next
request that will experience extra throttling, thus paying for the cost of the expensive
task.
Note: RateLimiter does not provide fairness guarantees.
| Method Summary | |
|---|---|
void |
acquire()
Acquires a permit from this RateLimiter, blocking until the request can be granted. |
void |
acquire(int permits)
Acquires the given number of permits from this RateLimiter, blocking until the
request be granted. |
static RateLimiter |
create(double permitsPerSecond)
Creates a RateLimiter with the specified stable throughput, given as
"permits per second" (commonly referred to as QPS, queries per second). |
static RateLimiter |
create(double permitsPerSecond,
long warmupPeriod,
TimeUnit unit)
Creates a RateLimiter with the specified stable throughput, given as
"permits per second" (commonly referred to as QPS, queries per second), and a
warmup period, during which the RateLimiter smoothly ramps up its rate,
until it reaches its maximum rate at the end of the period (as long as there are enough
requests to saturate it). |
double |
getRate()
Returns the stable rate (as permits per seconds) with which this
RateLimiter is configured with. |
void |
setRate(double permitsPerSecond)
Updates the stable rate of this RateLimiter, that is, the
permitsPerSecond argument provided in the factory method that
constructed the RateLimiter. |
String |
toString()
|
boolean |
tryAcquire(int permits,
long timeout,
TimeUnit unit)
Acquires the given number of permits from this RateLimiter if it can be obtained
without exceeding the specified timeout, or returns false
immediately (without waiting) if the permits would not have been granted
before the timeout expired. |
boolean |
tryAcquire(long timeout,
TimeUnit unit)
Acquires a permit from this RateLimiter if it can be obtained
without exceeding the specified timeout, or returns false
immediately (without waiting) if the permit would not have been granted
before the timeout expired. |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
| Method Detail |
|---|
public static RateLimiter create(double permitsPerSecond)
RateLimiter with the specified stable throughput, given as
"permits per second" (commonly referred to as QPS, queries per second).
The returned RateLimiter ensures that on average no more than permitsPerSecond are issued during any given second, with sustained requests
being smoothly spread over each second. When the incoming request rate exceeds
permitsPerSecond the rate limiter will release one permit every (1.0 / permitsPerSecond) seconds. When the rate limiter is unused,
bursts of up to permitsPerSecond permits will be allowed, with subsequent
requests being smoothly limited at the stable rate of permitsPerSecond.
permitsPerSecond - the rate of the returned RateLimiter, measured in
how many permits become available per second.
public static RateLimiter create(double permitsPerSecond,
long warmupPeriod,
TimeUnit unit)
RateLimiter with the specified stable throughput, given as
"permits per second" (commonly referred to as QPS, queries per second), and a
warmup period, during which the RateLimiter smoothly ramps up its rate,
until it reaches its maximum rate at the end of the period (as long as there are enough
requests to saturate it). Similarly, if the RateLimiter is left unused for
a duration of warmupPeriod, it will gradually return to its "cold" state,
i.e. it will go through the same warming up process as when it was first created.
The returned RateLimiter is intended for cases where the resource that actually
fulfils the requests (e.g., a remote server) needs "warmup" time, rather than
being immediately accessed at the stable (maximum) rate.
The returned RateLimiter starts in a "cold" state (i.e. the warmup period
will follow), and if it is left unused for long enough, it will return to that state.
permitsPerSecond - the rate of the returned RateLimiter, measured in
how many permits become available per secondwarmupPeriod - the duration of the period where the RateLimiter ramps up its
rate, before reaching its stable (maximum) rateunit - the time unit of the warmupPeriod argumentpublic final void setRate(double permitsPerSecond)
RateLimiter, that is, the
permitsPerSecond argument provided in the factory method that
constructed the RateLimiter. Currently throttled threads will not
be awakened as a result of this invocation, thus they do not observe the new rate;
only subsequent requests will.
Note though that, since each request repays (by waiting, if necessary) the cost
of the previous request, this means that the very next request
after an invocation to setRate will not be affected by the new rate;
it will pay the cost of the previous request, which is in terms of the previous rate.
The behavior of the RateLimiter is not modified in any other way,
e.g. if the RateLimiter was configured with a warmup period of 20 seconds,
it still has a warmup period of 20 seconds after this method invocation.
permitsPerSecond - the new stable rate of this RateLimiter.public final double getRate()
permits per seconds) with which this
RateLimiter is configured with. The initial value of this is the same as
the permitsPerSecond argument passed in the factory method that produced
this RateLimiter, and it is only updated after invocations
to setRate(double).
public void acquire()
RateLimiter, blocking until the request can be granted.
This method is equivalent to acquire(1).
public void acquire(int permits)
RateLimiter, blocking until the
request be granted.
permits - the number of permits to acquire
public boolean tryAcquire(long timeout,
TimeUnit unit)
RateLimiter if it can be obtained
without exceeding the specified timeout, or returns false
immediately (without waiting) if the permit would not have been granted
before the timeout expired.
This method is equivalent to tryAcquire(1, timeout, unit).
timeout - the maximum time to wait for the permitunit - the time unit of the timeout argument
true if the permit was acquired, false otherwise
public boolean tryAcquire(int permits,
long timeout,
TimeUnit unit)
RateLimiter if it can be obtained
without exceeding the specified timeout, or returns false
immediately (without waiting) if the permits would not have been granted
before the timeout expired.
permits - the number of permits to acquiretimeout - the maximum time to wait for the permitsunit - the time unit of the timeout argument
true if the permits were acquired, false otherwisepublic String toString()
toString in class Object
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||