Spring Cloud Gateway 如何将请求分发到各个服务

前言

在微服务架构中,API 网关(API Gateway)扮演着非常重要的角色。它负责接收客户端请求,并根据预定义的规则将请求路由到对应的后端服务。Spring Cloud Gateway 是 Spring 官方推出的一款高性能网关,支持动态路由、负载均衡、限流等功能。本文将详细介绍 Spring Cloud Gateway 的工作原理、配置方式以及如何实现请求分发,并附带源码和 UML 图示。


一、Spring Cloud Gateway 的核心概念

1.1 核心组件

  • Route(路由):网关的基本构建块,包含一个 ID、目标 URI 和一组断言(Predicate)和过滤器(Filter)。只有当请求满足断言条件时,才会被路由到指定的目标服务。
  • Predicate(断言):用于匹配 HTTP 请求中的特定条件,例如路径、方法、头信息等。
  • Filter(过滤器):对请求和响应进行处理,如修改请求头、添加日志、鉴权等。

1.2 工作流程图

以下是 Spring Cloud Gateway 的工作流程图:
客户端发送请求 Gateway 接收请求 匹配路由规则 执行全局过滤器 转发请求到目标服务 目标服务处理请求 返回响应到 Gateway 执行后置过滤器 返回响应给客户端


二、配置 Spring Cloud Gateway

2.1 引入依赖

pom.xml 文件中添加以下依赖:

xml 复制代码
<dependencies>
    <!-- Spring Cloud Gateway -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!-- Spring Boot WebFlux -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <!-- Spring Cloud Load Balancer (用于负载均衡) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>

2.2 配置路由规则

application.yml 中定义路由规则。以下是一个简单的示例:

yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user_service_route
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user/**
          filters:
            - AddRequestHeader=X-Gateway-Version, v1.0
        - id: order_service_route
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order/**
          filters:
            - AddResponseHeader=X-Gateway-Version, v1.0
配置说明:
  • id:路由的唯一标识符。
  • uri:目标服务地址,lb:// 表示使用负载均衡器(Load Balancer)。
  • predicates:定义匹配条件,例如路径 /user/**
  • filters:定义请求或响应的处理逻辑,例如添加请求头或响应头。

三、实现请求分发的核心逻辑

3.1 动态路由匹配

Spring Cloud Gateway 使用 Predicate 来匹配请求。以下是一个基于路径的分发逻辑示例:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("user_service_route", r -> r.path("/user/**")
                        .filters(f -> f.addRequestHeader("X-Gateway-Version", "v1.0"))
                        .uri("lb://USER-SERVICE"))
                .route("order_service_route", r -> r.path("/order/**")
                        .filters(f -> f.addResponseHeader("X-Gateway-Version", "v1.0"))
                        .uri("lb://ORDER-SERVICE"))
                .build();
    }
}
代码解析:
  • RouteLocatorBuilder 用于构建路由规则。
  • .path("/user/**") 匹配以 /user/ 开头的路径。
  • .uri("lb://USER-SERVICE") 将请求转发到注册中心的服务 USER-SERVICE

3.2 负载均衡

Spring Cloud Gateway 内置了对负载均衡的支持,通过 lb:// 协议可以实现服务发现和负载均衡。

示例场景:

假设有两个用户服务实例 USER-SERVICE-1USER-SERVICE-2 注册到了 Eureka 注册中心,Gateway 会根据负载均衡策略自动选择一个实例来处理请求。


3.3 自定义过滤器

除了内置过滤器,您还可以自定义过滤器来实现特定功能,例如鉴权、日志记录等。

以下是一个自定义过滤器的示例:

java 复制代码
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {

    public LoggingFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            System.out.println("请求路径:" + exchange.getRequest().getPath());
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                System.out.println("响应状态码:" + exchange.getResponse().getStatusCode());
            }));
        };
    }

    public static class Config {
        // 可以在这里定义配置参数
    }
}
使用自定义过滤器:

application.yml 中引用自定义过滤器:

yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user_service_route
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user/**
          filters:
            - LoggingFilter

四、完整示例

以下是一个完整的 Spring Cloud Gateway 示例,包括服务注册与发现、负载均衡和自定义过滤器。

4.1 项目结构

plaintext 复制代码
gateway-service/
├── src/main/java/com/example/gateway/
│   ├── GatewayApplication.java
│   ├── GatewayConfig.java
│   └── LoggingFilter.java
├── src/main/resources/
│   └── application.yml
└── pom.xml

4.2 启动类

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

4.3 配置文件

yaml 复制代码
server:
  port: 8080

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: user_service_route
          uri: lb://USER-SERVICE
          predicates:
            - Path=/user/**
          filters:
            - LoggingFilter
        - id: order_service_route
          uri: lb://ORDER-SERVICE
          predicates:
            - Path=/order/**
          filters:
            - AddResponseHeader=X-Gateway-Version, v1.0

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

五、总结

通过本文,我们详细介绍了 Spring Cloud Gateway 的核心概念、配置方式以及如何实现请求分发。以下是关键点总结:

  1. 核心组件:Route、Predicate 和 Filter 是 Gateway 的三大核心组件。
  2. 动态路由 :通过 Path 断言实现请求分发。
  3. 负载均衡:结合 Eureka 注册中心实现服务发现和负载均衡。
  4. 自定义过滤器:扩展 Gateway 功能,实现日志记录、鉴权等需求。

希望本文能帮助您快速上手 Spring Cloud Gateway,并将其应用到实际项目中。如果您有任何问题或建议,请随时留言交流!


参考资料

相关推荐
mask哥2 小时前
详解最新链路追踪skywalking框架介绍、架构、环境本地部署&配置、整合微服务springcloudalibaba 、日志收集、自定义链路追踪、告警等
java·spring cloud·架构·gateway·springboot·skywalking·链路追踪
liang89994 小时前
Docker(二):docker常用命令
spring cloud·docker·容器
来自星星的猫教授2 天前
spring,spring boot, spring cloud三者区别
spring boot·spring·spring cloud
Bling_2 天前
请求参数、路径参数、查询参数、Spring MVC/FeignClient请求相关注解梳理
java·spring·spring cloud·mvc
IT小辉同学2 天前
Docker如何更换镜像源提高拉取速度
spring cloud·docker·eureka
能来帮帮蒟蒻吗2 天前
Docker安装(Ubuntu22版)
笔记·学习·spring cloud·docker·容器
细心的莽夫3 天前
SpringCloud 微服务复习笔记
java·spring boot·笔记·后端·spring·spring cloud·微服务
lllsure3 天前
SpringCloud——负载均衡
服务器·网络·spring cloud
sinat_262292113 天前
Java面试实战:电商场景下的Spring Cloud微服务架构与缓存技术剖析
java·redis·spring cloud·微服务·消息队列·缓存技术·监控运维