use of com.google.common.util.concurrent.RateLimiter in project cassandra by apache.
the class RateBasedBackPressure method apply.
@Override
public void apply(Set<RateBasedBackPressureState> states, long timeout, TimeUnit unit) {
// Go through the back-pressure states, try updating each of them and collect min/max rates:
boolean isUpdated = false;
double minRateLimit = Double.POSITIVE_INFINITY;
double maxRateLimit = Double.NEGATIVE_INFINITY;
double minIncomingRate = Double.POSITIVE_INFINITY;
RateLimiter currentMin = null;
RateLimiter currentMax = null;
for (RateBasedBackPressureState backPressure : states) {
// Get the incoming/outgoing rates:
double incomingRate = backPressure.incomingRate.get(TimeUnit.SECONDS);
double outgoingRate = backPressure.outgoingRate.get(TimeUnit.SECONDS);
// Compute the min incoming rate:
if (incomingRate < minIncomingRate)
minIncomingRate = incomingRate;
// Try acquiring the interval lock:
if (backPressure.tryIntervalLock(windowSize)) {
// If acquired, proceed updating thi back-pressure state rate limit:
isUpdated = true;
try {
RateLimiter limiter = backPressure.rateLimiter;
// RateBasedBackPressureState):
if (outgoingRate > 0) {
// Compute the incoming/outgoing ratio:
double actualRatio = incomingRate / outgoingRate;
// If the ratio is above the high mark, try growing by the back-pressure factor:
if (actualRatio >= highRatio) {
// Only if the outgoing rate is able to keep up with the rate increase:
if (limiter.getRate() <= outgoingRate) {
double newRate = limiter.getRate() + ((limiter.getRate() * factor) / 100);
if (newRate > 0 && newRate != Double.POSITIVE_INFINITY) {
limiter.setRate(newRate);
}
}
} else // If below, set the rate limiter at the incoming rate, decreased by factor:
{
// Only if the new rate is actually less than the actual rate:
double newRate = incomingRate - ((incomingRate * factor) / 100);
if (newRate > 0 && newRate < limiter.getRate()) {
limiter.setRate(newRate);
}
}
logger.trace("Back-pressure state for {}: incoming rate {}, outgoing rate {}, ratio {}, rate limiting {}", backPressure.getHost(), incomingRate, outgoingRate, actualRatio, limiter.getRate());
} else // Otherwise reset the rate limiter:
{
limiter.setRate(Double.POSITIVE_INFINITY);
}
// Housekeeping: pruning windows and resetting the last check timestamp!
backPressure.incomingRate.prune();
backPressure.outgoingRate.prune();
} finally {
backPressure.releaseIntervalLock();
}
}
if (backPressure.rateLimiter.getRate() <= minRateLimit) {
minRateLimit = backPressure.rateLimiter.getRate();
currentMin = backPressure.rateLimiter;
}
if (backPressure.rateLimiter.getRate() >= maxRateLimit) {
maxRateLimit = backPressure.rateLimiter.getRate();
currentMax = backPressure.rateLimiter;
}
}
// Now find the rate limiter corresponding to the replica group represented by these back-pressure states:
if (!states.isEmpty()) {
// Get the rate limiter:
IntervalRateLimiter rateLimiter = rateLimiters.get(states, key -> new IntervalRateLimiter(timeSource));
// If the back-pressure was updated and we acquire the interval lock for the rate limiter of this group:
if (isUpdated && rateLimiter.tryIntervalLock(windowSize)) {
try {
// Update the rate limiter value based on the configured flow:
if (flow.equals(Flow.FAST))
rateLimiter.limiter = currentMax;
else
rateLimiter.limiter = currentMin;
tenSecsNoSpamLogger.info("{} currently applied for remote replicas: {}", rateLimiter.limiter, states);
} finally {
rateLimiter.releaseIntervalLock();
}
}
// Assigning a single rate limiter per replica group once per window size allows the back-pressure rate
// limiting to be stable within the group itself.
// Finally apply the rate limit with a max pause time equal to the provided timeout minus the
// response time computed from the incoming rate, to reduce the number of client timeouts by taking into
// account how long it could take to process responses after back-pressure:
long responseTimeInNanos = (long) (TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS) / minIncomingRate);
doRateLimit(rateLimiter.limiter, Math.max(0, TimeUnit.NANOSECONDS.convert(timeout, unit) - responseTimeInNanos));
}
}
use of com.google.common.util.concurrent.RateLimiter in project opennms by OpenNMS.
the class HeartbeatGenerator method start.
/**
* Start.
*/
public synchronized void start() {
stopped.set(false);
final RateLimiter rateLimiter = RateLimiter.create(rate);
thread = new Thread(new Runnable() {
@Override
public void run() {
while (!stopped.get()) {
rateLimiter.acquire();
try (Context ctx = sendTimer.time()) {
dispatcher.send(new Heartbeat());
sentMeter.mark();
}
}
}
});
thread.start();
}
use of com.google.common.util.concurrent.RateLimiter in project tesla by linking12.
the class RateLimitHttpRequestFilter method doFilter.
@Override
public HttpResponse doFilter(HttpRequest originalRequest, HttpObject httpObject, ChannelHandlerContext channelHandlerContext) {
if (httpObject instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest) httpObject;
String url = httpRequest.uri();
int index = url.indexOf("?");
if (index > -1) {
url = url.substring(0, index);
}
RateLimiter rateLimiter = null;
try {
rateLimiter = loadingCache.get(url);
} catch (Throwable e) {
}
// 如果1秒钟没有获取令牌,说明被限制了
if (rateLimiter != null && !rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
super.writeFilterLog(Double.toString(rateLimiter.getRate()), this.getClass(), "RateLimiter");
return super.createResponse(HttpResponseStatus.TOO_MANY_REQUESTS, originalRequest);
}
}
return null;
}
use of com.google.common.util.concurrent.RateLimiter in project free-framework by a601942905git.
the class LimiterTest1 method main.
public static void main(String[] args) {
RateLimiter rateLimiter = RateLimiter.create(5.0);
System.out.println(rateLimiter.acquire(5));
System.out.println(rateLimiter.acquire(2));
System.out.println(rateLimiter.acquire(1));
}
use of com.google.common.util.concurrent.RateLimiter in project free-framework by a601942905git.
the class RateLimiterTest method testWithRateLimiter.
public static void testWithRateLimiter() {
RateLimiter rateLimiter = RateLimiter.create(10);
Long start = Clock.systemDefaultZone().millis();
for (int i = 0; i < 20; i++) {
System.out.println(rateLimiter.acquire());
}
Long end = Clock.systemDefaultZone().millis();
System.out.println(end - start);
}
Aggregations