Gateway自定义限流规则

Gateway实现自定义限流规则

有些同学在使用gateway配置限流规则,可能需要自定义一些规则对哪些请求不限流。常规的做法是参考

org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory

继承或者实现其接口,来重写其

apply()

或者

isAllowed()

如图是Spring Cloud Gateway 3.1.1的默认实现
在这里插入图片描述
如果需要自定义限流的逻辑仅限于决定谁被限流,谁不被限流的话,可以看图中下面这段代码

@Override
public GatewayFilter apply(Config config) {
	KeyResolver resolver = getOrDefault(config.keyResolver, defaultKeyResolver);
	RateLimiter<Object> limiter = getOrDefault(config.rateLimiter, defaultRateLimiter);
	boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
	HttpStatusHolder emptyKeyStatus = HttpStatusHolder
			.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));

	return (exchange, chain) -> resolver.resolve(exchange).defaultIfEmpty(EMPTY_KEY).flatMap(key -> {
		if (EMPTY_KEY.equals(key)) { //如果等于EMPTY_KEY
			if (denyEmpty) {		//且denyEmpty为true,拦截请求
				setResponseStatus(exchange, emptyKeyStatus);
				return exchange.getResponse().setComplete();
			}
			return chain.filter(exchange); //否则放行,不限流
		}
		String routeId = config.getRouteId();
		if (routeId == null) {
			Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
			routeId = route.getId();
		}
		return limiter.isAllowed(routeId, key).flatMap(response -> {

			for (Map.Entry<String, String> header : response.getHeaders().entrySet()) {
				exchange.getResponse().getHeaders().add(header.getKey(), header.getValue());
			}

			if (response.isAllowed()) {
				return chain.filter(exchange);
			}

			setResponseStatus(exchange, config.getStatusCode());
			return exchange.getResponse().setComplete();
		});
	});
}

这里先判断了key值是否与EMPTY_KEY 相等
EMPTY_KEY 值如下:

private static final String EMPTY_KEY = "____EMPTY_KEY__";

又判断了变量denyEmpty的boolean值,如果为false则直接放行,不限流

所以我们可以通过调整denyEmpty的值为false,再将无需限流的请求key设置为字符串"__EMPTY_KEY",即可实现自定义限流 ~

首先是设置key,我们调整KeyResolver的逻辑,如下:

@Configuration
public class Config {

    private static final String EMPTY_KEY = "____EMPTY_KEY__";

    @Bean
    KeyResolver hostAddressKeyResolver() {
        return exchange -> {
            ServerHttpRequest serverHttpRequest = exchange.getRequest();
            if(serverHttpRequest.getHeaders().containsKey("此处举例,该逻辑替换成你需要的逻辑")){
                return Mono.just(EMPTY_KEY);
            }
            String key = Objects.requireNonNull(serverHttpRequest.getRemoteAddress()).getAddress().getHostAddress();//假设你也是根据host限流
            return Mono.just(key);
        };
    }
}

其次是denyEmpty的值,denyEmpty来源于配置文件,默认为true,源码如下

private boolean denyEmptyKey = true;//默认值

@Override
	public GatewayFilter apply(Config config) {
		...
		boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
		...
	}

	private <T> T getOrDefault(T configValue, T defaultValue) {
		return (configValue != null) ? configValue : defaultValue;
	}

所以我们可以调整如下配置

spring:
  cloud:
    gateway:
      routes:
        - id: ...
          uri: ...
          predicates:
            ...
          filters:
            - name: RequestRateLimiter
              args:
                key-resolver: "#{@自定义}"
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 1
                deny-empty-key: false

这样,对于我们 Mono.just(EMPTY_KEY)的请求,就可以实现不限流了。

以上代码仅基于Spring Cloud Gateway 3.1.1版本,供大家参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值