漏桶算法
漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率
令牌桶算法
令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.
令牌桶算法可以使用Google的guava
工具包来实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| import com.google.common.util.concurrent.RateLimiter;
import org.springframework.http.HttpStatus;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author itning
* @date 2020/3/25 20:47
*/
@SuppressWarnings("UnstableApiUsage")
@Component
public class RateLimitFilter extends OncePerRequestFilter {
private RateLimiter rateLimiter = RateLimiter.create(1);
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
if (rateLimiter.tryAcquire()) {
filterChain.doFilter(request, response);
} else {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
PrintWriter writer = response.getWriter();
writer.write(HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
writer.flush();
writer.close();
}
}
}
|
RateLimiter.create(1);
表示一秒钟最多处理一个请求
rateLimiter.tryAcquire()
返回的布尔值为true
表示获取到了令牌,而false
则表示没有获取到,被限流。
继承的OncePerRequestFilter
类是Spring
提供的过滤器类,能够保证每个请求只经过一次。
文章作者
itning
上次更新
2020年03月25日 21:08:38
许可协议
CC BY-NC-ND 4.0