令牌桶工作参数
工作过程包括3个阶段:产生令牌、消耗令牌和判断数据包是否通过。其中涉及到2个参数:令牌产生的速率CIR(Committed Information Rate)/EIR(Excess Information Rate)和令牌桶的大小CBS(Committed Burst Size)/EBS(Excess Burst Size)。下面用图形简要概括一下这3个阶段与2个参数的关系。 [1]
-
产生令牌:周期性的以速率CIR/EIR向令牌桶中增加令牌,桶中的令牌不断增多。如果桶中令牌数已到达CBS/EBS,则丢弃多余令牌。
-
消耗令牌:输入数据包会消耗桶中的令牌。在网络传输中,数据包的大小通常不一致。大的数据包相较于小的数据包消耗的令牌要多。
-
判断是否通过:输入数据包经过令牌桶后的结果包括输出的数据包和丢弃的数据包。当桶中的令牌数量可以满足数据包对令牌的需求,则将数据包输出,否则将其丢弃。
可以用RateLimiter这个类实现
RateLimiter类源码:
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.util.concurrent;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.Math.max;
import static java.util.concurrent.TimeUnit.MICROSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.util.concurrent.SmoothRateLimiter.SmoothBursty;
import com.google.common.util.concurrent.SmoothRateLimiter.SmoothWarmingUp;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.ThreadSafe;
/**
* A rate limiter. Conceptually, a rate limiter distributes permits at a configurable rate. Each
* {@link #acquire()} blocks if necessary until a permit is available, and then takes it. Once
* acquired, permits need not be released.
*
* <p>Rate limiters are often used to restrict the rate at which some physical or logical resource
* is accessed. This is in contrast to {@link java.util.concurrent.Semaphore} which restricts the
* number of concurrent accesses instead of the rate (note though that concurrency and rate are
* closely related, e.g. see <a href="http://en.wikipedia.org/wiki/Little%27s_law">Little's
* Law</a>).
*
* <p>A {@code 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.
*
* <p>It is possible to configure a {@code RateLimiter} to have a warmup period during which time
* the permits issued each second steadily increases until it hits the stable rate.
*
* <p>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: <pre> {@code
* final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per sec