美文网首页
spring cloud gateway中內置predicate

spring cloud gateway中內置predicate

作者: virtual灬zzZ | 来源:发表于2021-10-29 01:02 被阅读0次

spring cloud gateway中內置predicate、filter的使用,可以參考以下链接:

各种内置predicate、filter的使用

自定义filter、全局filter

先说全局filter,它是应用在所有的route的,看源码就知道,一个route的filter = 自身配的filter + defaultFilter + globalFilter。另外提一句,globalFilter往往都实现Orderer的,需要它个顺序,数值越小优先级越高,在后面filterHandlerMapping的时候,这些globalFilter会按顺序排好去执行的。

public interface GlobalFilter {

    /**
     * Process the Web request and (optionally) delegate to the next {@code WebFilter}
     * through the given {@link GatewayFilterChain}.
     * @param exchange the current server exchange
     * @param chain provides a way to delegate to the next filter
     * @return {@code Mono<Void>} to indicate when request processing is complete
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

}

GlobalFilter是一个接口,其实spring cloud gateway 里头已经有些定义好了的globalFilter,比如 NettyRoutingFilter、NettyWriteResponseFilter、ReactiveLoadBalancerClientFilter、NettyRoutingFilter & NettyWriteResponseFilter等等。


内置的globalFilter(有过时的) globalFilter的处理顺序

拿个ReactiveLoadBalancerClientFilter举例,ReactiveLoadBalancerClientFilter会根据 lb:// 前缀过滤处理,做负载均衡,选择最终要调用的服务地址,核心代码:

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    // 获取请求url和前缀
    URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
    // 获取url scheme前缀
    String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
    // 1.如果请求url为空,或者不是lb开头,那直接跳过处理
    if (url == null
            || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
        return chain.filter(exchange);
    }
    // 2.添加原始请求url到exchange里的GATEWAY_ORIGINAL_REQUEST_URL_ATTR(LinkedHashSet)
    addOriginalRequestUrl(exchange, url);
    return choose(exchange).doOnNext(response -> {
        // 3.获取负载均衡器,一般这里就是RibbonLoadBalancerClient
        ServiceInstance retrievedInstance = response.getServer();
        URI uri = exchange.getRequest().getURI();
        // 判断获取到的负载均衡器是用http还是https
        String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";
    // 假设请求url的scheme前缀不为空,这里的逻辑应该是有问题的
        // 如果schemePrefix不是lb,那早在第一步就结束了
        if (schemePrefix != null) {
            // 那么委托的负载均衡器请求也使用同样的scheme:lb
            overrideScheme = url.getScheme();
        }
        // 构造一个委托的负载均衡器
        DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(
            retrievedInstance, overrideScheme);
        // 由负载均衡器选出从多个提供服务的url里选出一个
        URI requestUrl = reconstructURI(serviceInstance, uri);
        // 然后把这个选出的url塞到ServerWebExchange里给其他过滤器用
        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
    }).then(chain.filter(exchange));  
}

自定义globalFilter

回归正题,我们可以自定义globalFilter,只需要实现globalFilter接口和ordered接口就行了。

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    public static final Integer CUSTOM_GLOBAL_FILTER_ORDER = 0;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("let us see what is ServerWebExchange : " + exchange);
        //直接下一个
        //return chain.filter(exchange);
        long startTime = System.currentTimeMillis();

        return chain.filter(exchange).then().then(Mono.fromRunnable(() -> {
            //调用请求之后统计时间
            long endTime = System.currentTimeMillis();
            System.out.println(exchange.getRequest().getURI().getRawPath() + ", cost time : " + (endTime - startTime) + "ms");
        }));
    }

    @Override
    public int getOrder() {
        return CUSTOM_GLOBAL_FILTER_ORDER;
    }

自定义局部filter

自定义局部filter,只需要实现gatewayFilter,同时往往也实现ordered,最后是实现构造工厂,如SetResponseHeaderGatewayFilterFactory,仿造就可以了,注意命名格式,因为需要在配置文件用,FilterDefination的提取问题。

public class CustomGatewayFilter implements GatewayFilter, Ordered {

    private AbstractNameValueGatewayFilterFactory.NameValueConfig config;

    public CustomGatewayFilter(AbstractNameValueGatewayFilterFactory.NameValueConfig config) {
        this.config = config;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("<-------------- BEGIN in custom gateway filter -------------->");
        System.out.println("do something before");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("do something after");
            System.out.println("custom gateway filter : " + toString());
            System.out.println("<-------------- END in custom gateway filter -------------->");
        }));
    }

    @Override
    public int getOrder() {
        return 123;
    }

    @Override
    public String toString() {
        return filterToStringCreator(this)
                .append(config.getName(), config.getValue()).toString();
    }
}
@Component //千万注意名字格式,XXX+GatewayFilterFactory
public class CustomGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory{

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new CustomGatewayFilter(config);
    }
}

最后在配置文件配置,filters那里,截取部分如下:

routes: #配置路由
        - id: consumer_low
          uri: http://192.168.1.106:8000
          predicates:
            - Path=/cs/** #路径
            - Weight=group1,2 #权重
            - After=2021-01-20T17:42:47.789+08:00[Asia/Shanghai] #在这时间后生效
            - Before=2022-01-20T17:42:47.789+08:00[Asia/Shanghai] #在这时间前生效
            - Between=2021-01-20T17:42:47.789+08:00[Asia/Shanghai],2022-01-20T17:42:47.789+08:00[Asia/Shanghai] #在这时间区间生效
            - Method=GET #请求方式
            - Cookie=orion, li.ly1 #cookies,key-value格式,只有key是包含这个参数,如果还有value就是key的值要满足value正则,http://192.168.1.106:9001/cs/gatewayPredicate/testCookie,带上cookie,注意domain,path=/,过期时间
            - Query=marit, lar.sen # 请求参数,key-value格式,只有key是包含这个参数,如果还有value就是key的值要满足value正则,http://192.168.1.106:9001/cs/gatewayPredicate/testParam?orion=likly
            - Header=mitch, lu.cker #请求头,key-value格式,只有key是包含这个参数,如果还有value就是key的值要满足value正则,http://192.168.1.106:9001/cs/gatewayPredicate/testHeader,Header加mitch=lugcker
          filters: # 网关过滤器
            - StripPrefix=1
            - Custom=wawa,lala

debug查看过滤器链:


debug

再看打印日志,可见其实是按filter chain来执行的:

<-------------- BEGIN in custom global filter -------------->
let us see what is ServerWebExchange : org.springframework.web.server.adapter.DefaultServerWebExchange@4c2e5532
<-------------- BEGIN in custom gateway filter -------------->
do something before
do something after
custom gateway filter : [CustomGatewayFilter wawa = 'lala']
<-------------- END in custom gateway filter -------------->
/cs/gatewayPredicate/testAll, cost time : 3850ms
<-------------- END in custom global filter -------------->

相关文章

网友评论

      本文标题:spring cloud gateway中內置predicate

      本文链接:https://www.haomeiwen.com/subject/kgyvaltx.html