「微服务网关实战三」详细理解 SCG 路由、断言与过滤器

又来给大家更文了。

本篇带给大家的是 SpringCloudGateway (下文简称 SCG)的各种断言与过滤器的讲解,由于在上一篇文章中我们已经使用过了断言与过滤器,但是一直没有对其进行大篇幅叙述,这可能会导致部分读者并不知道网关都具有哪些内置功能,所以本篇就是为了带大家全面的认识一下各种各样的断言以及过滤器,让大家在使用 SCG 做项目的时候更加明白:哪些功能需要自己做,哪些功能框架已经自带,避免重复造轮子,减少开发成本。

先赞后看,养成习惯,相信我的文章一定会让大家有所收获,废话不多说,开始了~

1. 路由

在使用 SCG 时,你要记住它的基本使用单位是路由,不是断言,也不是过滤器,断言和过滤器都只是路由的组成部分,所有的请求都是进入到路由中,然后根据路由的规则进行处理的。

在第一篇的时候,我曾经用过 SCG 官网的一张架构图,你可以用它再来做一个理解:

你可以将这张图看作 SCG 的一个路由,根据路由的断言它可以找到要请求的服务,然后在请求这个服务之前会先经过这个路由上的一堆过滤器,最终才是到达目标服务。

然而一个 SCG 肯定会有多个路由,而且很多情况下这些路由断言是有可能重复的,比如 /a 和 /** 这两个断言其实是重复的,这个时候我们还需要一个东西来标识谁在前,谁在后,那么路由里面除了断言和过滤器之外肯定还会有一个权重的概念,用它来处理断言重复情况下的优先级问题。

扯了这么多,我们已经知道一个路由必备的几个东西:断言、过滤器、代理服务、权重,那么接下来我们就看看 SCG 对于路由这个模型定义的数据结构 - RouteDefinition 吧:

/**
 * @author Spencer Gibb
 */
@Validated
public class RouteDefinition {
​
    // 唯一id
    private String id;
​
    @NotEmpty
    @Valid
    // 断言
    private List<PredicateDefinition> predicates = new ArrayList<>();
​
    @Valid
    // 过滤器
    private List<FilterDefinition> filters = new ArrayList<>();
​
    @NotNull
    // 代理服务
    private URI uri;
​
    // 元数据
    private Map<String, Object> metadata = new HashMap<>();
​
    // 权重
    private int order = 0;
​
}
​
复制代码

基本上和我们列举的分毫不差,就是多了一个用于区分路由的id,毕竟路由信息也是存储在内存中的一个 Map,如果没有一个唯一标识那是不行的,而且还多了一个 metadata,用于标识路由元数据,这个东西我们一般用不到,所以也不必关心。

我们在配置路由的时候其实就是配置这些数据,我们来看一下上篇文章中的一个例子:

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route((r) -> r.path("/user/**").uri("lb://user-api"))
            .route((r) -> r.path("/order/**").uri("lb://order-api"))
            .build();
}
复制代码

很明显这个配置 Bean 使用了建造者模式,这里的每一个 router 方法的参数里面装着的都是一个路由,但是可以发现我们在使用的时候并没有配置 id、过滤器和权重,这是因为在你不填的情况下它会默认帮你生成一个 UUID,而权重则默认是0,至于

<think>好的,用户现在问的是Spring Boot集成Gateway。之前他们问过关于Sentinel,所以我需要先回忆之前的对话内容。用户之前可能是在了解微服务相关的组件,比如流量控制高可用方案,现在转向API网关了。Spring Cloud Gateway是Spring官方推出的网关,替代了Zuul,所以需要重点介绍它的优势集成方法。 首先,用户可能是一个开发者,正在搭建微服务架构,需要了解如何用Spring Boot来集成网关。他们可能对网关的基本功能有需求,比如路由、过滤、限流等。之前提到过Sentinel的限流功能,这里可能需要对比或结合使用。 接下来,我需要确定回答的结构。可能包括Spring Cloud Gateway的概述、核心功能、集成步骤、配置方式(包括YMLJava代码)、过滤器链、全局过滤器、结合Sentinel做限流,以及常见问题。还要注意示例代码的正确性,确保用户能复制粘贴并运行。 用户可能的深层需求是希望实现一个高效的API网关,处理路由过滤,同时可能需要集成其他组件如Nacos或Sentinel。需要明确集成步骤,避免常见的配置错误。另外,他们可能对性能优化感兴趣,比如动态路由或响应式编程的优势。 需要检查是否有必要提到Spring Boot版本兼容性,比如Spring Cloud的版本对应关系,这可能会影响依赖配置。同时,全局过滤器自定义过滤器的示例代码要简洁明了,展示如何记录日志或添加头信息。 还要考虑用户可能遇到的问题,比如路由不生效、过滤器顺序问题,或者如何结合注册中心,给出解决方案或排查步骤。最后,确保语言口语化,避免技术术语过于密集,但保持专业性。</think>以下是关于 **Spring Boot 集成 Spring Cloud Gateway** 的详细介绍,涵盖核心概念、使用场景、配置方法及示例代码: --- ### **1. Spring Cloud Gateway 简介** **定位**:Spring 官方推出的 **API 网关**,基于 **Reactor 响应式编程模型**,专为微服务架构设计,用于路由转发、安全控制、限流熔断等场景。 **核心优势**: - 高性能:非阻塞异步模型(Netty 驱动),适合高并发场景。 - 灵活路由:支持动态配置路由规则(如路径、Header、请求参数等)。 - 过滤器链:提供全局局部过滤器,可自定义请求/响应处理逻辑。 - 集成生态:无缝兼容 Spring Cloud 体系(如 Nacos、Sentinel、Eureka)。 --- ### **2. 核心功能概念** | 功能/概念 | 说明 | |--------------------|--------------------------------------------------------------------| | **路由(Route)** | 定义请求如何转发到下游服务,包含ID、目标URI、断言(Predicate)、过滤器。 | | **断言(Predicate)** | 匹配请求的条件(如路径、Header、Method),决定是否应用该路由。 | | **过滤器(Filter)** | 处理请求响应的逻辑(如鉴权、日志、限流),支持全局局部作用域。 | --- ### **3. Spring Boot 集成步骤** #### **步骤 1:添加依赖** 在 `pom.xml` 中引入 Spring Cloud Gateway Spring Boot Starter: ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- 可选:集成服务发现(如Nacos) --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> ``` #### **步骤 2:配置路由规则** 在 `application.yml` 中定义路由(静态配置): ```yaml spring: cloud: gateway: routes: - id: user-service-route # 路由ID uri: http://localhost:8081 # 目标服务地址(或lb://service-name) predicates: # 断言条件 - Path=/user/** # 路径匹配 - Method=GET,POST # 请求方法匹配 filters: # 过滤器链 - StripPrefix=1 # 去除前缀(如/user/xxx → 转发到/xxx) - AddRequestHeader=X-User,admin # 添加请求头 ``` #### **步骤 3:动态路由(可选)** 通过代码动态配置路由(如从数据库读取): ```java @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("order-service", r -> r.path("/order/**") .filters(f -> f.rewritePath("/order/(?<segment>.*)", "/${segment}")) .uri("lb://order-service")) .build(); } ``` --- ### **4. 常用过滤器示例** #### **全局过滤器(Global Filter)** 记录请求日志: ```java @Component public class LoggingFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); System.out.println("Request Path: " + request.getPath()); return chain.filter(exchange); } } ``` #### **自定义局部过滤器** 添加响应头: ```java @Component public class AddResponseHeaderFilter implements GatewayFilterFactory<Object> { @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { ServerHttpResponse response = exchange.getResponse(); response.getHeaders().add("X-Custom-Header", "Hello Gateway"); return chain.filter(exchange); }; } } ``` --- ### **5. 集成 Sentinel 实现限流** 结合阿里巴巴 Sentinel 实现网关层限流: ```yaml spring: cloud: gateway: routes: - id: sentinel-demo uri: http://localhost:8082 predicates: - Path=/api/** sentinel: enabled: true # 开启Sentinel支持 scg: fallback: # 限流降级处理 mode: response response-status: 429 response-body: '{"code": 429, "msg": "请求过多,请稍后重试"}' ``` --- ### **6. 常见问题调试** | 问题 | 解决方案 | |-----------------------|------------------------------------------------------------------------| | **路由不生效** | 检查 `predicates` 是否匹配请求路径,`uri` 是否正确(如 `lb://` 需集成服务发现)。 | | **过滤器顺序混乱** | 使用 `Order` 注解或实现 `Ordered` 接口明确过滤器执行顺序。 | | **跨域问题** | 配置 `CorsConfiguration` 或使用 `@CrossOrigin` 注解。 | | **响应式编程兼容性** | 避免在过滤器中阻塞操作(如同步数据库调用),使用响应式API(如WebClient)。 | --- ### **7. 性能优化建议** 1. **启用缓存**:缓存路由配置,减少动态加载开销。 2. **精简过滤器链**:避免不必要的过滤器逻辑。 3. **结合注册中心**:使用 Nacos/Eureka 实现服务发现,动态更新路由。 4. **监控指标**:集成 Spring Boot Actuator 或 Prometheus 监控网关性能。 --- 通过以上配置示例,可快速搭建一个支持动态路由过滤器限流的 API 网关。是否需要进一步探讨具体场景(如鉴权、灰度发布)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值