SpringCloud H版 GateWay 过滤器讲解 及 使用Guava 统一限流处理。
Posted 小毕超
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud H版 GateWay 过滤器讲解 及 使用Guava 统一限流处理。相关的知识,希望对你有一定的参考价值。
一、GateWay
在上篇文章我们讲解了GateWay 的基本使用和路由的转发,在GateWay 中还有一个重要的知识点就是过滤器,基于过滤器我们可以限制请求的规范,比如过滤请求中token过期的请求,不做转发,或者在网关处对整个服务进行限流控制,保护内容服务的安全。
上篇文章地址:https://blog.csdn.net/qq_43692950/article/details/122023067
在上篇文章中就有提及过滤器,比如配制代理时,不要携带前缀,就使用了- StripPrefix=1
,GateWay 提供了很多自带的过滤器,大家也可以参考下每个官方的介绍,文本主要讲解如果自定义过滤器。
官方文档: https://docs.spring.io/spring-cloud-gateway/docs/3.0.5-SNAPSHOT/reference/html/
二、自定义过滤请求参数
教研过滤 参数和header
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
ServerHttpResponse response = exchange.getResponse();
ServerHttpRequest request = exchange.getRequest();
HttpHeaders header = response.getHeaders();
header.add("Content-Type", "application/json; charset=UTF-8");
String uid = request.getQueryParams().getFirst("uid");
if(StringUtils.isEmpty(uid))
JSONObject jsonObject = setResultErrorMsg("参数中必须传递uid");
DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
return response.writeWith(Mono.just(buffer));
List<String> list = exchange.getRequest().getHeaders().get("token");
if(list == null || list.isEmpty())
JSONObject jsonObject = setResultErrorMsg("header中必须传递token");
DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
return response.writeWith(Mono.just(buffer));
return chain.filter(exchange);
@Override
public int getOrder()
return 1;
private JSONObject setResultErrorMsg(String msg)
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "406");
jsonObject.put("message", msg);
return jsonObject;
浏览器请求其中一个转发接口,不传递任何参数:
添加上uid
下面在header中加入token
三、结合 Guava做接口的限流
@Component
@Slf4j
public class LimitFilter implements GlobalFilter, Ordered
//创建一个限流器,参数代表每秒生成的令牌数(用户限流频率设置 每秒中限制0.1个请求)
private RateLimiter rateLimiter = RateLimiter.create(0.1);
@Value("$seckill.intercept.url")
private List<String> gatewaySeckillInterceptUrl;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
ServerHttpResponse response = exchange.getResponse();
ServerHttpRequest request = exchange.getRequest();
HttpHeaders header = response.getHeaders();
header.add("Content-Type", "application/json; charset=UTF-8");
RequestPath path = request.getPath();
//设置等待超时时间的方式获取令牌,如果超timeout为0,则代表非阻塞,获取不到立即返回
boolean tryAcquire = rateLimiter.tryAcquire(1, TimeUnit.SECONDS);
if (!tryAcquire)
JSONObject jsonObject = setResultErrorMsg("当前访问用户过多,请稍后重试");
DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
return response.writeWith(Mono.just(buffer));
// 放行
return chain.filter(exchange);
private JSONObject setResultErrorMsg(String msg)
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "406");
jsonObject.put("message", msg);
return jsonObject;
@Override
public int getOrder()
return 0;
上面为了容易实现效果,配制了每秒生成0.1个请求,也就是10秒允许1个请求:
只要10秒内请求两次就可以出现上面这种情况。这种情况会将所有请求一律走限流处理。下面也可以修改为根据参数限流,限制每个url的并发请求,过滤器修改:
@Component
public class SeckillFilter implements GlobalFilter
//创建一个限流器,参数代表每秒生成的令牌数(用户限流频率设置 每秒中限制1个请求)
private RateLimiter rateLimiter = RateLimiter.create(1);
@Value("$gateway.seckill.intercept.url")
private List<String> gatewaySeckillInterceptUrl;
LoadingCache<String, RateLimiter> ipRequestCaches = CacheBuilder.newBuilder()
.maximumSize(1000)// 设置缓存个数
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, RateLimiter>()
@Override
public RateLimiter load(String s) throws Exception
return RateLimiter.create(0.1);// (限流每秒0.1个令牌响应,即10s一个令牌)
);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
ServerHttpResponse response = exchange.getResponse();
ServerHttpRequest request = exchange.getRequest();
HttpHeaders header = response.getHeaders();
header.add("Content-Type", "application/json; charset=UTF-8");
RequestPath path = request.getPath();
RateLimiter rateLimiter = null;
try
rateLimiter = ipRequestCaches.get(request.getURI().toString());
catch (ExecutionException e)
e.printStackTrace();
boolean tryAcquire = rateLimiter.tryAcquire();
if (!tryAcquire)
JSONObject jsonObject = setResultErrorMsg("当前访问用户过多,请稍后重试");
DataBuffer buffer = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
return response.writeWith(Mono.just(buffer));
// 放行
return chain.filter(exchange);
private JSONObject setResultErrorMsg(String msg)
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "406");
jsonObject.put("message", msg);
return jsonObject;
public static String getParam(String url, String name)
String params = url.substring(url.indexOf("?") + 1, url.length());
Map<String, String> split = Splitter.on("&").withKeyValueSeparator("=").split(params);
return split.get(name);
其实上面的也可以修改为根据token进行限流,这样就限制一个用户的请求的频率了。
喜欢的小伙伴可以关注我的个人微信公众号,获取更多学习资料!
以上是关于SpringCloud H版 GateWay 过滤器讲解 及 使用Guava 统一限流处理。的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud(Greenwich版)新一代API网关Gateway
#yyds干货盘点# springcloud整合gateway实现网关全局过滤器功能
SpringCloud 统一网关Gateway -- 全局过滤器 GlobalFilter@Order注解过滤器链执行顺序Gateway跨域问题处理
SpringCloud 统一网关Gateway -- 全局过滤器 GlobalFilter@Order注解过滤器链执行顺序Gateway跨域问题处理