spring cloud gateway 不生效

要说到gateway网关过滤,那一定要明白-过滤器-自定义局部、全局过滤器、区别。

前两天调试gateway网关问题,发现GatewayFilter和GlobalFilter使用错了,导致导致网关拦截失效,搞了一上午才找到问题。

spring cloud gateway 不生效

自定义过滤器需要实现GatewayFilterOrdered。其中GatewayFilter中的这个方法就是用来实现你的自定义的逻辑的

Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

示例:统计某个服务的响应时间

1.1、创建Filer

[复制代码](javascript:void(0); “复制代码”)

public class ElapsedFilter implements GatewayFilter, Ordered { private static final Log log = LogFactory.getLog(GatewayFilter.class); private static final String ELAPSED_TIME_BEGIN = "elapsedTimeBegin";

    @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(ELAPSED_TIME_BEGIN, System.currentTimeMillis()); return chain.filter(exchange).then(
                Mono.fromRunnable(() -> {
                    Long startTime = exchange.getAttribute(ELAPSED_TIME_BEGIN); if (startTime != null) {
                        log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms");
                    }
                })
        );
    }

    @Override public int getOrder() { return Ordered.LOWEST_PRECEDENCE;
    }
}

[复制代码](javascript:void(0); “复制代码”)

在请求刚刚到达时,往ServerWebExchange中放入了一个属性elapsedTimeBegin,属性值为当时的毫秒级时间戳。然后在请求执行结束后,又从中取出我们之前放进去的那个时间戳,与当前时间的差值即为该请求的耗时。因为这是与业务无关的日志所以将Ordered设为Integer.MAX_VALUE以降低优先级。

chain.filter(exchange)之前的就是 “pre” 部分,之后的也就是then里边的是 “post” 部分。

1.2、配置

创建好 Filter 之后我们将它添加到我们的 Filter Chain 里边

[复制代码](javascript:void(0); “复制代码”)

@Bean public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) { // @formatter:off
    return builder.routes()
            .route(r -> r.path("/fluent/customer/**")
                         .filters(f -> f.stripPrefix(2)
                                        .filter(new ElapsedFilter())
                                        .addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
                         .uri("lb://CONSUMER")
                         .order(0)
                         .id("fluent_customer_service")
            )
            .build(); // @formatter:on
}

[复制代码](javascript:void(0); “复制代码”)

注意:实际在使用 Spring Cloud 的过程中,需要使用 Sleuth+Zipkin 来进行耗时分析。

二、全局过滤器

有多个路由就需要一个一个来配置,并不能通过像下面这样来实现全局有效(也未在 Fluent Java API 中找到能设置 defaultFilters 的方法)

@Bean public ElapsedFilter elapsedFilter(){ return new ElapsedFilter();
}

自定义过滤器需要实现GlobalFilter和Ordered

示例:校验token

2.1、创建Filter

[复制代码](javascript:void(0); “复制代码”)

public class TokenFilter implements GlobalFilter, Ordered {

    @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token"); if (token == null || token.isEmpty()) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete();
        } return chain.filter(exchange);
    }

    @Override public int getOrder() { return -100;
    }
}

[复制代码](javascript:void(0); “复制代码”)

2.2、在 Spring Config 中配置这个 Bean

@Bean public TokenFilter tokenFilter(){ return new TokenFilter();
}

三、GatewayFilter与GlobalFilter的区别

3.1、GatewayFilter

在一个高的角度来看,Global filters会被应用到所有的路由上,而Gateway filter将应用到单个路由上或者一个分组的路由上。

GatewayFilter是从WebFilter中Copy过来的,相当于一个Filter过滤器,可以对访问的URL过滤横切处理,应用场景比如超时,安全等。

GatewayFilter和GlobalFilter两个接口中定义的方法一样都是Mono filter(ServerWebExchange exchange, GatewayFilterChain chain),唯一的区别就是GatewayFilter继承了ShortcutConfigurable,GlobalFilter没有任何继承。

参看示例一:Gateway Filter与RouteLocator绑定使用

3.2、GlobalFilter

Spring Cloud gateway定义了GlobalFilter的接口让我们去自定义实现自己的的GlobalFilter。GlobalFilter是一个全局的Filter,作用于所有的路由。

让其在Gateway中运行生效,有两种方式一种直接加[@Component](https://github.com/Component "@Component")注解,另外一种可以在 Spring Config 中配置这个 Bean如下示例二所示;

### Spring Cloud Gateway 网关 404 错误原因分析 Spring Cloud Gateway 是一个用于微服务架构中的 API 路由管理工具,其核心功能之一是通过定义路由规则来转发请求到目标服务。当出现 404 错误时,通常意味着客户端发送的请求无法被网关正确解析并匹配到对应的路由。 #### 原因一:路由配置错误 如果 `route` 配置不正确,则可能导致请求无法找到对应的服务路径。例如,在多个路由规则中,某些断言条件可能未按照优先级顺序排列[^3]。具体来说,具有更复杂断言逻辑的路由应放置在较简单的路由之前,以便能够先匹配复杂的场景再处理通用情况。 #### 解决方案一:调整路由优先级 对于存在多层次断言的情况(如 `/admin/**` 和 `/product/**`),需确保更加具体的路径模式位于较为宽泛的路径之上。这样可以避免由于模糊匹配而导致的目标资源不可达问题。例如: ```yaml spring: cloud: gateway: routes: - id: admin_route uri: lb://ADMIN-SERVICE predicates: - Path=/admin/** - id: product_route uri: lb://PRODUCT-SERVICE predicates: - Path=/product/** ``` 上述例子展示了如何设置两个不同服务之间的优先关系,其中管理员相关的操作会被优先考虑而不是落入商品查询之中。 #### 原因二:动态路由更新失败 在运行期间修改了网关项目的配置文件之后如果没有及时刷新上下文或者重新启动应用实例的话也可能引发类似的找不到页面的现象[^2]。这是因为新的更改尚未生效所致。 #### 解决方案二:手动触发配置重载机制 为了使最新的改动立即可用而无需每次都停机维护,可以通过 Actuator 提供的功能在线完成这一过程。比如调用 POST 请求至特定端点即可实现热部署效果: ```bash curl -X POST http://localhost:8080/actuator/refresh ``` 此命令适用于那些已经集成了 Spring Boot Admin 或者其他监控插件的应用程序环境当中。 ### 结论 综上所述,针对 Spring Cloud Gateway 中遇到的 HTTP Status Code 404 Not Found 的状况可以从以下几个方面入手排查以及修复: 1. 审核当前所有的 Route Predicate 是否合理安排; 2. 如果涉及到了实时变动的需求则记得适时通知框架同步最新状态信息; 以上措施有助于提升系统的稳定性和用户体验满意度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值