快速入门-Spring Cloud Gateway

92 阅读7分钟

快速入门-Spring Cloud Gateway

 小巫编程室

图片

Gateway(网关) 是一种服务组件,通常用作微服务架构中的入口点,负责请求的统一管理、路由转发、协议转换、安全认证、负载均衡等。Gateway 是客户端与后端服务之间的桥梁,简化了客户端的复杂性,同时增强了系统的安全性和灵活性。

在现代分布式系统架构中,微服务逐渐取代了传统的单体架构,成为主流的软件开发模式。微服务的优势包括模块化开发、高可用性、可扩展性等,但它也引入了以下复杂性和问题:服务数量增加,通信复杂化,不同服务的协议兼容性,缺乏统一的安全管理,性能和流量管理困难,监控和日志的分散。为了解决上述问题, Gateway 被引入作为一种集中式的流量管理工具。解决了微服务架构中的复杂性问题,包括通信管理、协议转换、安全性、性能优化等。它既是客户端与后端服务之间的桥梁,也是微服务治理的重要工具。在现代分布式架构中,Gateway 已成为不可或缺的组件。

Spring Cloud Gateway 是对 Netflix Zuul 的替代方案,专为微服务架构设计,基于 Spring Framework 和 Spring Boot,具有更高的性能和灵活性。

特点包括:

  • 高性能:基于非阻塞式 I/O(Netty)实现,性能优于传统的阻塞式网关(如 Zuul 1.x)。
  • 动态路由:支持根据路径、请求头、参数等条件动态路由请求。
  • 过滤器链:提供丰富的过滤器功能,可以对请求和响应进行修改,例如添加身份验证、限流等。
  • 集成 Spring 生态:无缝集成 Spring Security、Spring Cloud Config、Spring Actuator 等模块。

快速实践

可以参考:springdoc.cn/spring-clou…

# 环境准备
 
 1. JDK8以上版本
 2. 安装 Maven
 3. 下载并安装 Spring Boot 工程模板(可以通过 Spring Initializr)
 4. 构建一个SpringBoot项目


# 项目 pom 文件中引入依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

application 配置文件

spring:
#######################################    spring 微服务模块配置   ###################################
cloud:
    # 网关配置
    gateway:
      # 设置与服务注册发现组件结合,这样可以采用服务名的路由策略
      discovery:
        locator:
          enabled:true
          lower-case-service-id:true

      routes:
        -id:dotj-cloud-gateway    
         # 匹配微服务的名称, 或者微服务的地址          
          uri:lb://dotj-cloud-gateway     
          # uri: http://127.0.0.1:9090
          # 断言, 路径相互匹配的进行路由
          predicates:
            -Path=/gateway/**
          # 过滤掉前缀
          filters:
            -StripPrefix=1
     
## 说明
# id:随便写保持和其他服务不同就是了
# uri:说明要跳转的uri地址
# StripPrefix:指定要从源地址截取的个数,以“/“为分隔符。以地址栏输入“http://localhost:9090/gateway/say/** ”为例,域名部分不计,那就是从gateway/say/** 计算,StripPrefix=1,表示从前截取两个”/”,那么结构就是:/say/**,你的服务必须对应这个uri,否则会出现404。

Java代码


@RestController
@RequestMapping("/route")
public class RouteController {
    @Autowired
    private RouteDefinitionLocator routeDefinitionLocator;

    /**
     * test
     */
    @Operation(description = "test")
    @GetMapping("/test")
    public Mono<Result<?>> test() {
        String uuid = UUID.randomUUID().toString();
        return Mono.just(Result.success("test: " + uuid + "; test: " + test));
    }

    /**
     * 获取网关所有的路由信息
     *
     * @return
     */
    @Operation(description = "路由信息")
    @GetMapping("/list")
    public Flux<RouteDefinition> getRouteDefinitions() {
        return routeDefinitionLocator.getRouteDefinitions();
    }

}

Gateway 的重要概念

# Route(路由)

 路由是 Spring Cloud Gateway 的核心模块,用于定义请求转发规则。每个路由规则会根据指定的条件(Predicates)匹配请求,并将其转发到指定的目标服务。

 组成部分:
  1.ID:路由的唯一标识。
  2.URI:目标服务地址(可以是 HTTP 服务、WebSocket 服务等)。
  3.Predicates:条件匹配器,用于决定请求是否匹配当前路由规则。
  4.Filters:过滤器链,用于对请求和响应进行修改或拦截。 

# Predicate(断言)

 Predicate 是用于定义路由规则的条件判断模块。Gateway 会根据请求的属性(如路径、请求头、参数等)进行匹配,判断请求是否符合条件。

 常用 Predicates:
  1.Path:按路径匹配
    - Path=/api/**

  2.Method:按请求方法匹配
    - Method=GET

  3.Header:按请求头匹配
    - Header=X-Request-ID,123

  4.Query:按查询参数匹配
    - Query=type,user

  5.After/Before/Between:按时间范围匹配。
    - After=2025-01-01T00:00:00+08:00

  6.自定义 Predicate:
    开发者可以通过实现 RoutePredicateFactory 接口来自定义路由断言。


# Filter(过滤器)

 Filter 是用于对请求和响应进行处理的模块。过滤器可以用来实现身份验证、日志记录、限流、重写请求头等功能。

 分为两种:
  1.全局过滤器(GlobalFilters):作用于所有路由。
  2.局部过滤器(RouteFilters):作用于特定路由。

 常用内置过滤器:
  1.AddRequestHeader:添加请求头
   - AddRequestHeader=X-Request-ID,12345

  2.AddResponseHeader:添加响应头
   - AddResponseHeader=X-Response-Time,500ms

  3.RewritePath:重写请求路径
   - RewritePath=/old/(?<segment>.*), /new/${segment}

  自定义 Filter
   通过实现 GatewayFilter 接口,可以创建自定义过滤器。


# Gateway Handler(处理器)

 Gateway Handler 是 Gateway 中的核心调度器,负责
  1.将请求分发给合适的路由。
  2.触发相关的过滤器链。
  3.转发请求到目标服务并返回结果。

 Gateway Handler 依赖于 Routing Predicate 和 Filter Chain 的运行结果,确保所有匹配的逻辑和操作都被执行。


# Filter Chain(过滤器链)

 Filter Chain 是过滤器的集合,按顺序执行所有过滤器。请求处理包含两个阶段:
  1.Pre Filters:在请求到达后端服务之前执行。
  2.Post Filters:在后端服务响应返回给客户端之前执行。

 过滤器链的执行逻辑类似于拦截器的链式调用。

自定义过滤器

@Component
publicclass CustomFilter implements GlobalFilterOrdered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 预处理逻辑
        System.out.println("Pre-Filter logic here");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 后处理逻辑
            System.out.println("Post-Filter logic here");
        }));
    }

    @Override
    public int getOrder() {
        return -1// 优先级,越小越高
    }
}

自定义过滤器规则

@Component
publicclass TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.Config> {
    privatestaticfinal Logger logger = LoggerFactory.getLogger(TestGatewayFilterFactory.class);
    // 在类的构造器中一定要调用下父类的构造器把Config类型传过去,否则会报ClassCastException
    public TestGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public String name() {
        return"TestGatewayFilterFactory";
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            return chain.filter(exchange).then(
                    Mono.fromRunnable(() -> {})
            );
        };
    }

    publicstaticclass Config {
        privateboolean withParams;
        public boolean isWithParams() {
            return withParams;
        }
        public void setWithParams(boolean withParams) {
            this.withParams = withParams;
        }
    }
}

配置文件事例

spring:
  cloud:
    gateway:
      # 路由数组:指当请求满足什么样的断言时,转发到哪个服务上
      routes:
        # 路由标识,要求唯一,名称任意
        -id:gateway-provider_1
    # 请求最终被转发到的目标地址
          uri:http://localhost:9024
          # 设置断言
          predicates:
            # Path Route Predicate Factory 断言,满足 /gateway/provider/** 路径的请求都会被路由到 http://localhost:9024 这个uri中
            -Path=/gateway/provider/**
            # Weight Route Predicate Factory 断言,同一分组按照权重进行分配流量,这里分配了80%
            # 第一个group1是分组名,第二个参数是权重
            -Weight=group1,8
          # 配置过滤器(局部)
          filters:
            # StripPrefix:去除原始请求路径中的前1级路径,即/gateway
            -StripPrefix=1            
            
        -id:gateway-provider_2
          uri:http://localhost:9025
          # 设置断言
          predicates:
            -Path=/gateway/provider/**
            # Weight Route Predicate Factory,同一分组按照权重进行分配流量,这里分配了20%
            -Weight=group1,2
    # 配置过滤器(局部)
          filters:
            # StripPrefix:去除原始请求路径中的前1级路径,即/gateway
            -StripPrefix=1            

总结

图片

Spring Cloud Gateway 是基于 Spring WebFlux 构建的高效 API 网关,作为微服务架构的统一流量入口,提供动态路由、过滤器、负载均衡、限流和熔断等功能,与 Spring 生态无缝集成,适合高并发和灵活扩展的场景。它简化了客户端与服务的交互流程,统一了认证、安全和流量控制,提升了系统的稳定性与可维护性,是现代微服务架构的重要组件。

致谢

更多内容欢迎关注 [ 小巫编程室 ] 公众号,喜欢文章的话,也希望能给小编点个赞或者转发,你们的喜欢与支持是小编最大的鼓励,小巫编程室感谢您的关注与支持。好好学习,天天向上(good good study day day up)。

参考资料

[1] 官网: spring.io/projects/sp…

[2] 源码: github.com/spring-clou…