Spring Cloud Gateway 完整学习指南

Spring Cloud Gateway 完整学习指南

目录

​​​​​​​

1. 什么是Spring Cloud Gateway

1.1 定义与背景

1.2 为什么需要API网关

1.3 Spring Cloud Gateway的优势

2. 核心概念详解

2.1 Route(路由)

2.2 Predicate(断言)

2.3 Filter(过滤器)

3. 工作原理深入分析

3.1 请求处理流程

3.2 线程模型

4. 环境搭建与基础配置

4.1 项目依赖配置

4.2 基础配置文件

4.3 启动类配置

5. 路由配置详解

5.1 静态路由配置

5.2 动态路由配置

6. 断言(Predicate)完全指南

6.1 路径断言(Path Route Predicate)

6.2 方法断言(Method Route Predicate)

6.3 请求头断言(Header Route Predicate)

6.4 查询参数断言(Query Route Predicate)

6.5 时间断言(DateTime Route Predicates)

6.6 自定义断言

7. 过滤器(Filter)深度解析

7.1 内置过滤器详解

7.2 请求和响应修改过滤器

7.3 重试过滤器

7.4 熔断器过滤器

7.5 自定义过滤器

8. 全局过滤器应用

8.1 全局过滤器概述

8.2 请求追踪过滤器

8.3 性能监控过滤器

8.4 响应缓存过滤器

9. 限流策略实现

9.1 基于Redis的限流

9.2 自定义限流算法

9.3 分层限流策略

10. 负载均衡配置

10.1 基于服务发现的负载均衡

10.2 自定义负载均衡算法

10.3 负载均衡器配置

10.4 健康检查与故障转移

11. 监控与健康检查

11.1 Actuator端点配置

11.2 自定义健康检查

11.3 Prometheus指标集成

11.4 日志配置与分析

11.5 分布式追踪集成

12. 安全配置实践

12.1 HTTPS配置

12.2 认证授权集成

12.3 CORS配置

12.4 安全头配置

13. 实际项目应用案例

13.1 电商系统网关设计

13.2 微服务网格集成

13.3 多环境路由策略

14. 性能优化与最佳实践

14.1 性能调优配置

14.2 缓存策略实现

14.3 连接池优化

14.4 内存优化

14.5 监控最佳实践

15. 常见问题与解决方案

15.1 常见配置问题

15.2 性能问题排查

15.3 安全问题解决

15.4 调试技巧
​​​​​​​

​​​​​​​


1. 什么是Spring Cloud Gateway

1.1 定义与背景

Spring Cloud Gateway是Spring Cloud生态系统中的API网关服务,它是第二代网关实现,用来替代第一代的***flix Zuul。Spring Cloud Gateway基于Spring 5、Spring Boot 2和Project Reactor等技术构建,提供了一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能。

1.2 为什么需要API网关

在微服务架构中,我们面临以下挑战:

客户端复杂性问题

  • 客户端需要与多个微服务进行交互
  • 不同服务可能使用不同的协议(HTTP、gRPC等)
  • 服务实例的动态变化给客户端带来困扰

横切关注点问题

  • 认证授权逻辑分散在各个服务中
  • 限流、监控、日志记录等功能重复实现
  • 跨域处理在每个服务中都需要配置

服务治理问题

  • 缺乏统一的请求入口
  • 难以实现全局的流量控制
  • 服务间调用关系复杂,难以管理

1.3 Spring Cloud Gateway的优势

高性能

  • 基于***ty和WebFlux实现,支持非阻塞I/O
  • 内存占用更少,吞吐量更高
  • 支持异步处理,响应速度更快

易于扩展

  • 丰富的内置断言和过滤器
  • 支持自定义断言和过滤器
  • 基于Spring Framework,集成简单

功能强大

  • 支持动态路由配置
  • 提供多种负载均衡策略
  • 内置限流、重试、熔断等功能

2. 核心概念详解

2.1 Route(路由)

路由是Gateway中最基本的组件,它由一个ID、一个目标URI、一组断言和一组过滤器定义。

路由的组成部分

  • ID:路由的唯一标识符,用于区分不同的路由规则
  • URI:请求转发的目标地址,可以是具体的服务地址或服务名
  • Predicate:断言,用于匹配HTTP请求的各种属性
  • Filter:过滤器,用于在请求处理过程中进行修改或增强

路由匹配流程

  1. 客户端发送请求到Gateway
  2. Gateway遍历所有路由定义
  3. 使用断言判断请求是否匹配当前路由
  4. 如果匹配成功,应用相应的过滤器
  5. 将请求转发到目标服务

2.2 Predicate(断言)

断言用于匹配HTTP请求的任何内容,比如请求头、请求参数、请求路径等。只有当断言为真时,路由才会进行请求转发。

常用断言类型

  • Path:基于请求路径匹配
  • Method:基于HTTP方法匹配
  • Header:基于请求头匹配
  • Query:基于查询参数匹配
  • Cookie:基于Cookie匹配
  • Host:基于Host匹配
  • RemoteAddr:基于远程地址匹配

2.3 Filter(过滤器)

过滤器是Gateway的核心功能之一,用于在请求被路由前后进行修改。过滤器可以修改请求和响应的内容、头信息等。

过滤器类型

  • Pre类型过滤器:在请求被转发之前执行
  • Post类型过滤器:在响应返回给客户端之前执行

过滤器作用范围

  • 局部过滤器:只对特定路由生效
  • 全局过滤器:对所有路由都生效

3. 工作原理深入分析

3.1 请求处理流程

客户端请求 -> Gateway Handler Mapping -> Web Handler -> 过滤器链 -> 目标服务
                      ↓
                   路由匹配
                      ↓
                   断言验证
                      ↓
                   过滤器执行

详细流程说明

  1. 请求接收:Gateway接收客户端的HTTP请求
  2. 路由匹配:Handler Mapping根据配置的路由规则查找匹配的路由
  3. 断言验证:执行路由中配置的断言,判断请求是否符合条件
  4. 过滤器执行:按照pre -> routing -> post的顺序执行过滤器
  5. 请求转发:将处理后的请求转发到目标服务
  6. 响应处理:接收目标服务的响应,执行post过滤器
  7. 响应返回:将最终处理后的响应返回给客户端

3.2 线程模型

Spring Cloud Gateway基于Reactor模式,采用事件驱动的非阻塞I/O模型:

Reactor模式特点

  • 单线程事件循环处理I/O事件
  • 所有I/O操作都是非阻塞的
  • 通过回调函数处理异步结果
  • 内存使用效率高,支持大量并发连接

优势体现

  • 减少线程切换的开销
  • 降低内存消耗
  • 提高系统吞吐量
  • 更好的可扩展性

4. 环境搭建与基础配置

4.1 项目依赖配置

创建一个新的Spring Boot项目,添加必要的依赖:

<dependencies>
    <!-- Spring Cloud Gateway -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
    <!-- 服务注册发现(可选) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-***flix-eureka-client</artifactId>
    </dependency>
    
    <!-- 配置中心(可选) -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    
    <!-- 监控和健康检查 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

4.2 基础配置文件

application.yml中配置基本信息:

server:
  port: 8080

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      # 全局跨域配置
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true
      
      # 路由配置
      routes:
        - id: user-service
          uri: http://localhost:8081
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix=1

# 日志配置
logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    reactor.***ty: DEBUG

4.3 启动类配置

@SpringBootApplication
@EnableEurekaClient  // 如果使用Eureka
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

5. 路由配置详解

5.1 静态路由配置

静态路由配置是在配置文件中直接定义路由规则,适用于路由规则相对固定的场景。

YAML配置方式

spring:
  cloud:
    gateway:
      routes:
        # 用户服务路由
        - id: user-service-route
          uri: http://localhost:8081
          predicates:
            - Path=/api/user/**
            - Method=GET,POST
          filters:
            - StripPrefix=2
            - AddRequestHeader=X-Request-Source, gateway
        
        # 订单服务路由
        - id: order-service-route
          uri: lb://order-service  # 负载均衡
          predicates:
            - Path=/api/order/**
            - Header=Authorization, Bearer.*
          filters:
            - StripPrefix=2
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20

Java配置方式

@Configuration
public class GatewayConfig {
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                // 用户服务路由
                .route("user-service-route", r -> r
                        .path("/api/user/**")
                        .and()
                        .method(HttpMethod.GET, HttpMethod.POST)
                        .filters(f -> f
                                .stripPrefix(2)
                                .addRequestHeader("X-Request-Source", "gateway")
                                .retry(retryConfig -> retryConfig
                                        .setRetries(3)
                                        .setStatuses(HttpStatus.BAD_GATEWAY)
                                        .setMethods(HttpMethod.GET)
                                        .setBackoff(Duration.ofMillis(100), Duration.ofMillis(1000), 2, true)
                                )
                        )
                        .uri("http://localhost:8081")
                )
                // 订单服务路由
                .route("order-service-route", r -> r
                        .path("/api/order/**")
                        .and()
                        .header("Authorization", "Bearer.*")
                        .filters(f -> f
                                .stripPrefix(2)
                                .requestRateLimiter(rl -> rl
                                        .setRateLimiter(redisRateLimiter())
                                        .setKeyResolver(userKeyResolver())
                                )
                        )
                        .uri("lb://order-service")
                )
                .build();
    }
    
    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(10, 20, 1);
    }
    
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(
            exchange.getRequest().getHeaders().getFirst("user-id")
        );
    }
}

5.2 动态路由配置

动态路由允许在运行时添加、修改或删除路由规则,通常与配置中心结合使用。

使用Nacos配置中心

@RefreshScope
@RestController
@RequestMapping("/gateway")
public class GatewayController {
    
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    
    @Autowired
    private ApplicationEventPublisher publisher;
    
    /**
     * 添加路由
     */
    @PostMapping("/route")
    public Mono<ResponseEntity<String>> addRoute(@RequestBody RouteDefinition routeDefinition) {
        return routeDefinitionWriter.save(Mono.just(routeDefinition))
                .then(Mono.defer(() -> {
                    publisher.publishEvent(new RefreshRoutesEvent(this));
                    return Mono.just(ResponseEntity.ok("路由添加成功"));
                }));
    }
    
    /**
     * 删除路由
     */
    @DeleteMapping("/route/{id}")
    public Mono<ResponseEntity<String>> deleteRoute(@PathVariable String id) {
        return routeDefinitionWriter.delete(Mono.just(id))
                .then(Mono.defer(() -> {
                    publisher.publishEvent(new RefreshRoutesEvent(this));
                    return Mono.just(ResponseEntity.ok("路由删除成功"));
                }));
    }
}

自定义路由加载器

@***ponent
public class DatabaseRouteDefinitionRepository implements RouteDefinitionRepository {
    
    @Autowired
    private RouteService routeService;
    
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<GatewayRoute> routes = routeService.findAllRoutes();
        return Flux.fromIterable(routes)
                .map(this::convertToRouteDefinition);
    }
    
    private RouteDefinition convertToRouteDefinition(GatewayRoute route) {
        RouteDefinition definition = new RouteDefinition();
        definition.setId(route.getId());
        definition.setUri(URI.create(route.getUri()));
        
        // 设置断言
        List<PredicateDefinition> predicates = new ArrayList<>();
        PredicateDefinition pathPredicate = new PredicateDefinition();
        pathPredicate.setName("Path");
        pathPredicate.addArg("pattern", route.getPath());
        predicates.add(pathPredicate);
        definition.setPredicates(predicates);
        
        // 设置过滤器
        List<FilterDefinition> filters = new ArrayList<>();
        if (route.getStripPrefix() > 0) {
            FilterDefinition stripPrefixFilter = new FilterDefinition();
            stripPrefixFilter.setName("StripPrefix");
            stripPrefixFilter.addArg("parts", String.valueOf(route.getStripPrefix()));
            filters.add(stripPrefixFilter);
        }
        definition.setFilters(filters);
        
        return definition;
    }
}

6. 断言(Predicate)完全指南

6.1 路径断言(Path Route Predicate)

路径断言是最常用的断言类型,用于匹配请求的URL路径。

基础用法

spring:
  cloud:
    gateway:
      routes:
        - id: path-route
          uri: http://example.org
          predicates:
            - Path=/red/{segment},/blue/{segment}

高级用法

// 支持正则表达式
.route("path-route", r -> r
    .path("/api/user/{id:[0-9]+}")  // 只匹配数字ID
    .uri("http://user-service")
)

// 多路径匹配
.route("multi-path-route", r -> r
    .path("/api/user/**", "/api/profile/**")
    .uri("http://user-service")
)

路径变量提取

@***ponent
public class PathVariableFilter implements GatewayFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Map<String, String> uriVariables = ServerWebExchangeUtils
            .getUriTemplateVariables(exchange);
        
        String userId = uriVariables.get("id");
        // 可以将路径变量添加到请求头中
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-User-Id", userId)
            .build();
            
        return chain.filter(exchange.mutate().request(request).build());
    }
}

6.2 方法断言(Method Route Predicate)

用于匹配HTTP请求方法。

spring:
  cloud:
    gateway:
      routes:
        - id: method-route
          uri: http://example.org
          predicates:
            - Method=GET,POST

实际应用场景

# 读操作路由到读服务
- id: read-service
  uri: lb://read-service
  predicates:
    - Path=/api/data/**
    - Method=GET,HEAD,OPTIONS

# 写操作路由到写服务
- id: write-service
  uri: lb://write-service
  predicates:
    - Path=/api/data/**
    - Method=POST,PUT,DELETE

6.3 请求头断言(Header Route Predicate)

用于匹配请求头信息。

spring:
  cloud:
    gateway:
      routes:
        - id: header-route
          uri: http://example.org
          predicates:
            - Header=X-Request-Id, \d+  # 请求头值必须是数字

复杂请求头匹配

.route("api-version-route", r -> r
    .header("API-Version", "v[1-2]")  // 匹配v1或v2版本
    .and()
    .header("Content-Type", "application/json.*")
    .uri("http://api-service")
)

6.4 查询参数断言(Query Route Predicate)

用于匹配查询参数。

spring:
  cloud:
    gateway:
      routes:
        - id: query-route
          uri: http://example.org
          predicates:
            - Query=green  # 必须包含green参数
            - Query=red, gree.  # red参数值必须匹配正则表达式

实际应用

// 根据API版本路由
.route("api-v1-route", r -> r
    .query("version", "1\\..*")
    .uri("http://api-v1-service")
)
.route("api-v2-route", r -> r
    .query("version", "2\\..*")
    .uri("http://api-v2-service")
)

6.5 时间断言(DateTime Route Predicates)

用于根据时间条件进行路由。

spring:
  cloud:
    gateway:
      routes:
        # 在指定时间之后生效
        - id: after-route
          uri: http://example.org
          predicates:
            - After=2024-01-20T17:42:47.789-07:00[America/Denver]
        
        # 在指定时间之前生效
        - id: before-route
          uri: http://example.org
          predicates:
            - Before=2024-01-20T17:42:47.789-07:00[America/Denver]
        
        # 在指定时间范围内生效
        - id: between-route
          uri: http://example.org
          predicates:
            - Between=2024-01-20T17:42:47.789-07:00[America/Denver], 2024-01-21T17:42:47.789-07:00[America/Denver]

实际应用场景

// 灰度发布:新版本只在特定时间段开放
.route("new-version-route", r -> r
    .path("/api/**")
    .and()
    .between(
        ZonedDateTime.now().plusHours(2),  // 2小时后开始
        ZonedDateTime.now().plusDays(7)    // 7天后结束
    )
    .uri("http://new-service")
)

6.6 自定义断言

创建自定义断言来满足特殊的业务需求。

@***ponent
public class CustomPredicateFactory extends AbstractRoutePredicateFactory<CustomPredicateFactory.Config> {
    
    public CustomPredicateFactory() {
        super(Config.class);
    }
    
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            String userType = exchange.getRequest().getHeaders().getFirst("User-Type");
            return config.getUserType().equals(userType);
        };
    }
    
    @Data
    public static class Config {
        private String userType;
    }
    
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("userType");
    }
}

使用自定义断言

spring:
  cloud:
    gateway:
      routes:
        - id: custom-route
          uri: http://example.org
          predicates:
            - Custom=VIP  # 只有VIP用户才能访问

7. 过滤器(Filter)深度解析

7.1 内置过滤器详解

Spring Cloud Gateway提供了丰富的内置过滤器,满足大部分常见需求。

AddRequestHeader过滤器

spring:
  cloud:
    gateway:
      routes:
        - id: add-request-header-route
          uri: http://example.org
          filters:
            - AddRequestHeader=X-Request-Source, gateway
            - AddRequestHeader=X-Request-Time, #{T(System).currentTimeMillis()}

AddResponseHeader过滤器

filters:
  - AddResponseHeader=X-Response-Source, gateway
  - AddResponseHeader=X-Response-Time, #{T(System).currentTimeMillis()}

StripPrefix过滤器

# 将 /api/user/profile 转换为 /user/profile
filters:
  - StripPrefix=1

RewritePath过滤器

# 将 /red/blue 重写为 /blue
filters:
  - RewritePath=/red(?<segment>/?.*), $\{segment}

SetPath过滤器

# 将路径设置为 /foo/bar
filters:
  - SetPath=/foo/bar

PrefixPath过滤器

# 在路径前添加前缀
filters:
  - PrefixPath=/api

7.2 请求和响应修改过滤器

ModifyRequestBody过滤器

@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("modify-request-body-route", r -> r
            .path("/api/transform")
            .filters(f -> f
                .modifyRequestBody(String.class, String.class, 
                    (exchange, s) -> Mono.just(s.toUpperCase()))
            )
            .uri("http://example.org")
        )
        .build();
}

ModifyResponseBody过滤器

.filters(f -> f
    .modifyResponseBody(String.class, String.class,
        (exchange, s) -> {
            // 在响应中添加时间戳
            JsonNode jsonNode = objectMapper.readTree(s);
            ((ObjectNode) jsonNode).put("timestamp", System.currentTimeMillis());
            return Mono.just(jsonNode.toString());
        }
    )
)

7.3 重试过滤器

配置请求重试机制:

spring:
  cloud:
    gateway:
      routes:
        - id: retry-route
          uri: http://example.org
          filters:
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY,GATEWAY_TIMEOUT
                methods: GET,POST
                backoff:
                  firstBackoff: 50ms
                  maxBackoff: 500ms
                  factor: 2
                  basedOnPreviousValue: false

自定义重试逻辑

@***ponent
public class CustomRetryFilter implements GatewayFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange)
            .onErrorResume(TimeoutException.class, ex -> {
                // 超时异常的特殊处理
                log.warn("Request timeout, implementing fallback strategy");
                return handleTimeout(exchange);
            })
            .retry(3)
            .doOnError(error -> {
                log.error("Request failed after retries: {}", error.getMessage());
            });
    }
    
    private Mono<Void> handleTimeout(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.SERVICE_UNAVAILABLE);
        DataBuffer buffer = response.bufferFactory().wrap("Service temporarily unavailable".getBytes());
        return response.writeWith(Mono.just(buffer));
    }
    
    @Override
    public int getOrder() {
        return -1;
    }
}

7.4 熔断器过滤器

集成Spring Cloud Circuit Breaker:

spring:
  cloud:
    gateway:
      routes:
        - id: circuitbreaker-route
          uri: http://example.org
          filters:
            - name: CircuitBreaker
              args:
                name: myCircuitBreaker
                fallbackUri: forward:/fallback

配置Resilience4j熔断器

resilience4j:
  circuitbreaker:
    instances:
      myCircuitBreaker:
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        failureRateThreshold: 50
        waitDurationInOpenState: 60000
        permittedNumberOfCallsInHalfOpenState: 3

自定义降级处理

@RestController
public class FallbackController {
    
    @RequestMapping("/fallback")
    public Mono<Map<String, Object>> fallback(ServerWebExchange exchange) {
        Map<String, Object> result = new HashMap<>();
        result.put("code", 503);
        result.put("message", "Service temporarily unavailable");
        result.put("timestamp", System.currentTimeMillis());
        result.put("path", exchange.getRequest().getPath().value());
        
        return Mono.just(result);
    }
}

7.5 自定义过滤器

创建自定义过滤器来实现特定的业务逻辑:

转载请说明出处内容投诉
CSS教程网 » Spring Cloud Gateway 完整学习指南

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买