前言: 刚刚把博客加了个限流器,想着既然限流加了限制名单也就一起加上吧。啥也不用讲开干!就在刚刚触发限流的地方把添加进限制名单
加入限流
try {
limiter.acquire(0, TimeUnit.MILLISECONDS,(x) -> { return null; });
} catch (LimiterException e) {
BlockIpRule rule = new BlockIpRule();
rule.setExpirationTime(System.currentTimeMillis() + 600000);
rule.setIp(IPKit.getIpAddr(request));
blockListOperation.put(rule);
//重定向
response.sendRedirect("/error/404");
return;
}
判断是否在限制名单中
新建 BlockListFilter过滤器
/**
* Same contract as for {@code doFilter}, but guaranteed to be
* just invoked once per request within a single request thread.
* See {@link #shouldNotFilterAsyncDispatch()} for details.
* <p>Provides HttpServletRequest and HttpServletResponse arguments instead of the
* default ServletRequest and ServletResponse ones.
*
* @param request
* @param response
* @param filterChain
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String uri = request.getRequestURI();
//错误业务不加限流
if(StrUtil.isBlank(uri) || !uri.startsWith("/error")){
if(blockList.accept(IPKit.getIpAddr(request))){
//重定向
response.sendRedirect("/error/404");
return;
}
}
filterChain.doFilter(request, response);
}
BlockListOperation接口
一个“限制名单操作接口”
/**
* @author: HeHui
* @date: 2020-06-17 11:28
* @description: 黑名单操作类
*/
public interface BlockListOperation {
/**
* 添加一个黑名单规则
* @param rule 规则
*/
void put(BlockIpRule rule);
/**
* 移除一个黑名单规则
* @param rule 规则
*/
void remove(BlockIpRule rule) throws NotDelException;
/**
* 延长规则时间
* @param rule 规则
* @param ms 毫秒
*/
void extended(IpRule rule,int ms);
/**
* 查询一个黑名单规则
* @param ip
* @return
*/
BlockIpRule find(String ip);
有两个实现
- LocalBinarySearchBlockListOperation 二分查找实现
- LocalBloomFilterBlockListOperation 布隆过滤器实现
结尾: 其实被限流的人也挺无辜的,是前面的人把许可都用完了怎么到我就限流了呢??哈~哈哈. 是可以做到针对IP限流的。但是这样就需要每一个IP都有一个单独的Limiter(这还得了,划不来划不来)。还是等网关部署了在解决这个问题吧
评论区