• Spring Gateway 全局过滤器 Global Filters


    原文档地址:点这里

    6. Global Filters

    GlobalFilter接口和GatewayFilter接口都只有一个相同的方法,这些特殊的过滤器可以有条件的应用于所有的路由。(这些接口和用法在以后的版本中可能会被修改)。

    6.1 Combined Global Filter and GatewayFilter Ordering(过滤器的执行顺序)

    当一个请求到达一个Gateway的路由时,Filtering Web Handler会加载所有的GlobalFilter实例以及这个路由上配置的所有的GatewayFilter过滤器,然后组成一个完整的过滤链。这个过滤链中过滤器使用org.springframework.core.Ordered接口进行排序,可以通过实现Ordered接口中的getOrder()方法或直接使用@Order注解修改过滤器的顺序。

    由于Spring Cloud Gateway分开执行“pre”和“post”的过滤器,(可以参考前面讲Gateway如何工作的章节),因此,优先级高的过滤器将先执行“pre”类型的过滤器,最后执行“post”类型的的过滤器,如下面代码所示:

    @Bean
    @Order(-1)
    public GlobalFilter a() {
        return (exchange, chain) -> {
            log.info("first pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("third post filter");
            }));
        };
    }
    
    @Bean
    @Order(0)
    public GlobalFilter b() {
        return (exchange, chain) -> {
            log.info("second pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("second post filter");
            }));
        };
    }
    
    @Bean
    @Order(1)
    public GlobalFilter c() {
        return (exchange, chain) -> {
            log.info("third pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("first post filter");
            }));
        };
    }

    从上面的代码可以看出,“pre”类型的过滤器是在(exchanges,chain)->{}中执行的,而“post”类型的过滤器是在chain.filter(exchange).then(Mono.fromRunnable(()->{}))中执行的。

     

    6.2 Forward Routing Filter

     这个全局过滤器的实现类是:ForwardRoutingFilter,请求过来吧,它会从exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);获取路由配置的URI,如果这个URI是forward模式,过滤器会将请求转发到DispatcherHandler,然后匹配到网关本的请求路径之中,原来请求的URI将被forward的URI覆盖,原始的请求URI被存储到exchange的ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性之中。

    例如下面的配置:

    - id: forward_routing_filter
            uri: forward:///app
            order: 10000
            predicates:
            - Path=/forwardFilter
            filters:
            - PrefixPath=/gateway

    在spring-cloud-gateway中添加跳转的FowardRoutingFilterController,来用接收跳转之后的请求:

    @RestController
    @RequestMapping("gateway")
    public class FowardRoutingFilterController {
        @RequestMapping("app")
        public String  globalFilters() {
            return "Forward跳转成功";
        }
    }

    在浏览器中输入:http://localhost:8080/forwardFilter,在spring-cloud-gateway服务收到请求之后,会执行以下步骤:

    • 根据请求路径/forwardFilter匹配到路由forward_routing-filter,并将请求跳转为:http://localhost:8080/app
    • filters里面的PrefixPath配置请求改写为:http://localhost:8080/gateway/app
    • ForwardRoutingFilter过滤器中判断路由中有foroward://前缀,将请求转发给DispatcherHandler
    • DispatcherHandler匹配并转到spring-cloud-gateway服务中的contoller匹配的路径

    为了方便看到路径的变化,我们可以定义一个全局的过滤器:MyGlobalFitlers ,如下面代码所示:

    @Service
    public class MyGlobalFitlers implements GlobalFilter, Ordered{
    
        private Logger logger = LoggerFactory.getLogger(MyGlobalFitlers.class);
        @Override
        public int getOrder() {
            return 10001;
        }
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            Object value = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
            Object after = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
            logger.debug("global filters:{},{}",value,after);
            return chain.filter(exchange);
        }
    
    }

    在浏览器中输入:http://localhost:8080/forwardFilter,在控制台上日志可以看到前后不同的两个请求地址:

    global filters:http://localhost:8080/gateway/app,[http://localhost:8080/app]

    6.3 LoadBalancerClient Filter

    这个全局过滤器的实现类是:LoadBalancerClientFilter,它是用来处理负载均衡的过滤器。在网关后面的服务可以启动多个服务实例,这个过滤器就是把请求根据均衡规则路由到某台服务实例上面。它从exchange的ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性中获取URI,如果这个URI的scheme是“lb”,如:lb://myserivce,它会使用spring cloud 的LoadBalancerClient解析myservice服务名,获取一个服务实例的host和port,并替换原来的客户端请求。原来请求的url会存储在exchange的ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR属性中。这个过滤器也会从exchange中获取ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR属性值,如果它的值也是“lb”,也会使用相同的规则路由。

    如下面配置:

    - id: balanceclient_route
            uri: lb://app-a
            predicates:
            - Path=/app-a/app/**

    app-a是服务的名字,即spring.application.name的值 ,启动两个app-a的服务,在浏览器中输入http://localhost:8080/app-a/app/balance,点击多次,可以看到app-a的两个服务实例都有日志输入,说明每个实例都被请求到了,实现了负载均衡。

     注意:默认情况下,如果LoadBalancer根据配置的实例名找不到有效的服务实例,返回状态码503,如果你想配置返回404,可以这样设置:

    spring.cloud.gateway.loadbalancer.use404=true

    另外,Loadbalancer找到的服务实例ServiceInstance的方法isSecure的值,会覆盖请求中的scheme,比如如果请求网关的url的scheme是https,但是isSecure的值是false,在转发请求的时候,请求url的scheme会变成http,反过来也是一样的。但是,如果exchange的GATEWAY_SCHEME_PREFIX_ATTR属性在网关配置中被指定某个值,那么这个值将会覆盖ServiceInstance的配置。

    6.4 Netty Routing Filter

    这个全局过滤器的实现类是:NettyRoutingFilter,这是一个优先级最低的过滤器,如果从exchange的ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR获取的URL的scheme是https或http,它将使用Netty的HttpClient创建向下执行的请求代理,请求返回的结果将存储在exchange的ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR属性中,过滤器链后面的过滤器可以从中获取返回的结果。(还有一个测试使用的过滤器,WebClientHttpRoutingFilter,它和NettyRoutingFilter的功能一样,但是不使用netty)。

    6.5 Netty Write Response Filter

    这个全局过滤器的实现类是:NettyWriteResponseFilter,它的优先级是最高的,它是“post”类型的过滤器。如果在exchange中ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR的属性存在HttpClientResponse,它会在所有的其它的过滤器执行完成之后运行,将响应的数据发送给网关的客户端。

    6.6 RouteToRequestUrl Filter

    这个全局过滤器的实现类是:RouteToRequestUrlFilter,它的作用是把浏览器的URL请求的Path路径添加到路由的URI之中,比如浏览器请求网关的URL是:http://localhost:8080/app-a/app/balance,路由的URI配置是:uri: lb://app-a,那么添加之后的路由的URI是:lb://app-a/app/balance,并将它存储在exchange的ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR属性之中。

    6.7 Websocket Routing Filter

    这个全局过滤器的实现类是:WebsocketRoutingFilter,它是用来路由WebScoket请求,在exchange的ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR的URI中,如果scheme是ws或wss,它会使用Spring Web Socket 模块转发WebSocket请求。WebSockets可以使用路由进行负载均衡,比如:lb:ws://serviceid 

    如果在客户端使用了SockJS,那么应该配置一个普通的Http路由。如下面配置所示:

    spring:
      cloud:
        gateway:
          routes:
          # SockJS route
          - id: websocket_sockjs_route
            uri: http://localhost:3001
            predicates:
            - Path=/websocket/info/**
          # Normwal Websocket route
          - id: websocket_route
            uri: ws://localhost:3001
            predicates:
            - Path=/websocket/**

    6.8 Gateway Metrics Filter

    这个全局过滤器的实现类是:GatewayMetricsFilter,它用来统计一些网关的性能指标。需要添加spring-boot-starter-actuator的项目依赖,

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>

    默认情况下,只要spring.cloud.gateway.metrics.enabled设置不是false,这个过滤器就生效。这个过滤器会添加一个名字为“gateway.requests”和tags为如下的timer metric:

    • routeId: 路由的id
    • routeUri:被路由的URI
    • outcome:被HttpStatus.Series标记的结果
    • status : 返回给客户端的http状态码

    这些指标可以通过/actuator/metrics/gateway.requests查看,但是需要开启权限,如下面application.yml配置:

    management: 
      endpoints: 
        web: 
          exposure:  
            include: "*"

    注意,如果网关一次都没有被请求过,这时请求/actuator/metrics/gateway.requests会返回404,网关必须被请求过一次,才会正常返回监控的一些指标。

    而且网关的这些监控指标可以整合到Prometheus,创建一个Grafana dashboard。

    Prometheus是一款监控工具,Grafana是一款监控可视化工具;Spring Boot Actuator可与这两款工具进行整合,需要添加micrometer-registry-prometheus依赖

            <dependency>
                <groupId>io.micrometer</groupId>
                <artifactId>micrometer-registry-prometheus</artifactId>
            </dependency>

     第二件1.9元】草原传奇 白蘑牛肉酱180g*2瓶香辣牛肉酱蘑菇酱拌饭酱拌面酱内蒙特产 草原传奇白蘑牛肉酱 2瓶

    6.9 Making An Exchange As Routed

    如果网关已经路由过一个ServerWebExchange,它将标记这个exchange已经被路由过,记录在exchange的ServerWebExchangeUtils.GATEWAY_ALREADY_ROUTED_ATTR属性中。一旦被标记完成了路由,其它的路由过滤器将不会再路由本次请求,直接跳过此过滤器。有两个方便的方法,你可以使用它们标记已路由过或检测是否已路由过

    • ServerWebExchangeUtils.isAlreadyRouted takes a ServerWebExchange object and checks if it has been "routed"
    • ServerWebExchangeUtils.setAlreadyRouted takes a ServerWebExchange object and marks it as "routed"
  • 相关阅读:
    异步非阻塞
    jdbc简单入门
    网络编程
    多线程
    java方法
    java之面向对象
    java-多线程
    Java之反射机制
    使用C#完成冒泡排序
    TextEdit不能空验证设置
  • 原文地址:https://www.cnblogs.com/wgslucky/p/11632572.html
Copyright © 2020-2023  润新知