Spring Cloud Gateway 网关技术文档

Spring Cloud Gateway 网关技术文档

1. 引言

在微服务架构中,API网关是系统的入口点,负责请求路由、负载均衡、安全认证、限流熔断等核心功能。Spring Cloud Gateway是Spring Cloud生态系统中的新一代API网关组件,它基于Spring Boot 2.x和Spring WebFlux构建,提供了高性能、响应式的网关服务。

Spring Cloud Gateway具有以下主要特点:

  • 响应式编程模型:基于WebFlux构建,支持高并发、低延迟的响应式编程
  • 动态路由:支持动态配置和更新路由规则
  • 强大的过滤器链:提供丰富的内置过滤器和自定义过滤器支持
  • 限流和熔断:集成Redis实现限流,支持与Hystrix、Resilience4j等熔断组件集成
  • 安全认证:与Spring Security无缝集成,支持OAuth2、JWT等认证方式
  • 监控和可观测性:提供详细的监控指标和日志支持
  • 与Spring Cloud生态集成:与Eureka、Consul、Nacos等服务注册中心无缝集成

本文将详细介绍Spring Cloud Gateway的核心概念、架构设计、安装配置、路由规则、过滤器、限流熔断等功能,并提供实际的Java代码示例,帮助读者快速上手Spring Cloud Gateway开发。

2. 核心概念

2.1 Gateway

Gateway是Spring Cloud Gateway的核心组件,负责接收所有客户端请求,并根据配置的路由规则将请求转发到相应的后端服务。

2.2 Route

Route是Spring Cloud Gateway的基本构建块,代表一个路由规则。每个Route包含以下属性:

  • ID:路由的唯一标识符
  • URI:目标服务的URI
  • Predicates:路由断言集合,用于匹配请求
  • Filters:过滤器集合,用于修改请求和响应

2.3 Predicate

Predicate是路由断言,用于判断请求是否匹配某个路由规则。Spring Cloud Gateway提供了丰富的内置断言,如路径断言、方法断言、头断言等。

2.4 Filter

Filter是过滤器,用于在请求被路由到后端服务之前或之后修改请求和响应。Spring Cloud Gateway提供了两种类型的过滤器:

  • GatewayFilter:局部过滤器,仅应用于特定的路由
  • GlobalFilter:全局过滤器,应用于所有路由

2.5 Gateway Handler Mapping

Gateway Handler Mapping负责根据路由断言匹配请求,并将匹配的请求转发到相应的Gateway Handler。

2.6 Gateway Web Handler

Gateway Web Handler负责执行过滤器链,并将请求转发到后端服务。

2.7 Filter Chain

FilterChain是过滤器链,包含多个过滤器,用于在请求处理过程中执行一系列操作。

3. 架构设计

3.1 整体架构

Spring Cloud Gateway的整体架构由以下几个核心组件组成:

  1. 客户端请求:来自客户端的HTTP请求
  2. Gateway Handler Mapping:根据路由断言匹配请求
  3. Gateway Web Handler:执行过滤器链
  4. FilterChain:包含多个GatewayFilter和GlobalFilter
  5. 后端服务:目标微服务

3.2 工作流程

Spring Cloud Gateway的工作流程如下:

  1. 客户端发送HTTP请求到Spring Cloud Gateway
  2. Gateway Handler Mapping根据请求的属性(如路径、方法、头信息等)匹配相应的路由
  3. 如果匹配到路由,将请求转发到Gateway Web Handler
  4. Gateway Web Handler执行过滤器链
    • 前置过滤器:在请求被转发到后端服务之前执行
    • 路由转发:将请求转发到后端服务
    • 后置过滤器:在收到后端服务响应之后执行
  5. 将响应返回给客户端

3.3 响应式编程模型

Spring Cloud Gateway基于Spring WebFlux构建,采用响应式编程模型。响应式编程模型具有以下优势:

  • 高并发:基于Reactor框架,支持非阻塞I/O,能够处理大量并发请求
  • 低延迟:减少线程上下文切换和资源消耗,提高系统响应速度
  • 更好的资源利用率:使用少量线程即可处理大量请求,提高服务器资源利用率
  • 更好的弹性:支持背压机制,能够处理流量峰值

4. 安装与配置

4.1 创建Spring Cloud Gateway项目

4.1.1 使用Spring Initializr
  1. 访问Spring Initializr:https://start.spring.io/
  2. 选择Spring Boot版本(建议2.4.0+)
  3. 添加以下依赖:
    • Spring Cloud Gateway
    • Spring Cloud Starter Netflix Eureka Client(可选,用于服务发现)
    • Spring Boot Starter Actuator(可选,用于监控)
    • Spring Boot Starter Security(可选,用于安全认证)
  4. 生成项目并下载
4.1.2 使用Maven
xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>3.1.3</version>
</dependency>

<!-- 服务发现依赖(可选) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>3.1.3</version>
</dependency>

<!-- 监控依赖(可选) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>2.6.8</version>
</dependency>

<!-- 安全认证依赖(可选) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.6.8</version>
</dependency>

4.2 基本配置

4.2.1 配置文件

Spring Cloud Gateway支持两种配置方式:properties和yaml。以下是一个基本的yaml配置示例:

yaml 复制代码
spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: http://localhost:8081
          predicates:
            - Path=/api/users/**
          filters:
            - RewritePath=/api/users/(?<segment>.*), /users/$
4.2.2 服务发现配置

如果使用服务发现(如Eureka),可以配置为从服务注册中心获取后端服务地址:

yaml 复制代码
spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - RewritePath=/api/users/(?<segment>.*), /users/$

# 服务发现配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
4.2.3 主类
java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现(可选)
public class GatewayServiceApplication {

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

5. 路由配置

5.1 路由定义

路由是Spring Cloud Gateway的核心配置,用于定义请求如何被转发到后端服务。每个路由包含ID、URI、断言和过滤器。

5.1.1 基于配置文件的路由
yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        # 路由1
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - RewritePath=/api/users/(?<segment>.*), /users/$
        
        # 路由2
        - id: order-service-route
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - RewritePath=/api/orders/(?<segment>.*), /orders/$
5.1.2 基于Java代码的路由
java 复制代码
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                // 路由1
                .route("user-service-route", r -> r
                        .path("/api/users/**")
                        .filters(f -> f
                                .rewritePath("/api/users/(?<segment>.*)", "/users/$")
                        )
                        .uri("lb://user-service")
                )
                // 路由2
                .route("order-service-route", r -> r
                        .path("/api/orders/**")
                        .filters(f -> f
                                .rewritePath("/api/orders/(?<segment>.*)", "/orders/$")
                        )
                        .uri("lb://order-service")
                )
                .build();
    }
}

5.2 路由URI

路由URI支持以下几种协议:

  • http/https:转发到HTTP/HTTPS服务
  • lb:负载均衡,转发到服务注册中心中的服务
  • ws/wss:转发到WebSocket服务
yaml 复制代码
# HTTP服务
uri: http://localhost:8081

# 负载均衡
uri: lb://user-service

# WebSocket服务
uri: ws://localhost:8082

5.3 动态路由

Spring Cloud Gateway支持动态路由,可以通过配置中心(如Spring Cloud Config)或API动态更新路由规则。

5.3.1 使用配置中心
  1. 添加配置中心依赖:
xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
    <version>3.1.3</version>
</dependency>
  1. 配置配置中心:
yaml 复制代码
spring:
  cloud:
    config:
      uri: http://localhost:8888
      name: gateway-service
      profile: dev
  1. 在配置中心中定义路由规则,Gateway会自动刷新路由配置。
5.3.2 使用API动态路由

Spring Cloud Gateway提供了RouteDefinitionRepository接口,可以实现自定义的路由仓库,支持动态添加、删除和更新路由。

java 复制代码
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {

    private final Map<String, RouteDefinition> routes = new ConcurrentHashMap<>();

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        return Flux.fromIterable(routes.values());
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            routes.put(routeDefinition.getId(), routeDefinition);
            return Mono.empty();
        });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (routes.containsKey(id)) {
                routes.remove(id);
            }
            return Mono.empty();
        });
    }
}

6. 路由断言

路由断言用于判断请求是否匹配某个路由规则。Spring Cloud Gateway提供了丰富的内置断言,也支持自定义断言。

6.1 内置断言

6.1.1 路径断言(Path)

路径断言用于匹配请求路径:

yaml 复制代码
predicates:
  - Path=/api/users/**
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .uri("lb://user-service")
)
6.1.2 方法断言(Method)

方法断言用于匹配HTTP请求方法:

yaml 复制代码
predicates:
  - Method=GET,POST
java 复制代码
.route("user-service-route", r -> r
        .method("GET", "POST")
        .uri("lb://user-service")
)
6.1.3 头断言(Header)

头断言用于匹配请求头:

yaml 复制代码
predicates:
  - Header=X-Request-Id, \d+
java 复制代码
.route("user-service-route", r -> r
        .header("X-Request-Id", "\\d+")
        .uri("lb://user-service")
)
6.1.4 参数断言(Query)

参数断言用于匹配请求参数:

yaml 复制代码
predicates:
  - Query=name
  - Query=age, \d+
java 复制代码
.route("user-service-route", r -> r
        .query("name")
        .query("age", "\\d+")
        .uri("lb://user-service")
)
6.1.5 主机断言(Host)

主机断言用于匹配请求主机:

yaml 复制代码
predicates:
  - Host=**.example.com
java 复制代码
.route("user-service-route", r -> r
        .host("**.example.com")
        .uri("lb://user-service")
)
6.1.6 Cookie断言(Cookie)

Cookie断言用于匹配请求Cookie:

yaml 复制代码
predicates:
  - Cookie=sessionId, \w+
java 复制代码
.route("user-service-route", r -> r
        .cookie("sessionId", "\\w+")
        .uri("lb://user-service")
)
6.1.7 权重断言(Weight)

权重断言用于实现负载均衡:

yaml 复制代码
routes:
  - id: user-service-v1
    uri: lb://user-service-v1
    predicates:
      - Path=/api/users/**
      - Weight=group1, 80
  - id: user-service-v2
    uri: lb://user-service-v2
    predicates:
      - Path=/api/users/**
      - Weight=group1, 20
java 复制代码
.route("user-service-v1", r -> r
        .path("/api/users/**")
        .weight("group1", 80)
        .uri("lb://user-service-v1")
)
.route("user-service-v2", r -> r
        .path("/api/users/**")
        .weight("group1", 20)
        .uri("lb://user-service-v2")
)
6.1.8 时间断言(After/Before/Between)

时间断言用于匹配请求时间:

yaml 复制代码
predicates:
  - After=2023-01-01T00:00:00+08:00[Asia/Shanghai]
  - Before=2024-01-01T00:00:00+08:00[Asia/Shanghai]
  - Between=2023-01-01T00:00:00+08:00[Asia/Shanghai], 2024-01-01T00:00:00+08:00[Asia/Shanghai]
java 复制代码
import java.time.ZonedDateTime;

.route("user-service-route", r -> r
        .after(ZonedDateTime.parse("2023-01-01T00:00:00+08:00[Asia/Shanghai]"))
        .uri("lb://user-service")
)
6.1.9 远程地址断言(RemoteAddr)

远程地址断言用于匹配客户端IP地址:

yaml 复制代码
predicates:
  - RemoteAddr=192.168.1.0/24
java 复制代码
.route("user-service-route", r -> r
        .remoteAddr("192.168.1.0/24")
        .uri("lb://user-service")
)

6.2 自定义断言

可以通过实现RoutePredicateFactory接口来自定义断言:

java 复制代码
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {

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

    @Validated
    public static class Config {
        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("value");
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        return exchange -> {
            // 自定义断言逻辑
            String requestValue = exchange.getRequest().getQueryParams().getFirst("custom");
            return config.getValue().equals(requestValue);
        };
    }
}

使用自定义断言:

yaml 复制代码
predicates:
  - Custom=test
java 复制代码
.route("user-service-route", r -> r
        .predicate(new CustomRoutePredicateFactory().apply(config -> {
            config.setValue("test");
            return config;
        }))
        .uri("lb://user-service")
)

7. 过滤器

过滤器用于在请求被路由到后端服务之前或之后修改请求和响应。Spring Cloud Gateway提供了两种类型的过滤器:

  • GatewayFilter:局部过滤器,仅应用于特定的路由
  • GlobalFilter:全局过滤器,应用于所有路由

7.1 内置GatewayFilter

7.1.1 重写路径过滤器(RewritePath)

重写路径过滤器用于重写请求路径:

yaml 复制代码
filters:
  - RewritePath=/api/users/(?<segment>.*), /users/$
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .rewritePath("/api/users/(?<segment>.*)", "/users/$")
        )
        .uri("lb://user-service")
)
7.1.2 添加请求头过滤器(AddRequestHeader)

添加请求头过滤器用于添加请求头:

yaml 复制代码
filters:
  - AddRequestHeader=X-Request-Id, 123456
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .addRequestHeader("X-Request-Id", "123456")
        )
        .uri("lb://user-service")
)
7.1.3 添加响应头过滤器(AddResponseHeader)

添加响应头过滤器用于添加响应头:

yaml 复制代码
filters:
  - AddResponseHeader=X-Response-Id, 123456
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .addResponseHeader("X-Response-Id", "123456")
        )
        .uri("lb://user-service")
)
7.1.4 移除请求头过滤器(RemoveRequestHeader)

移除请求头过滤器用于移除请求头:

yaml 复制代码
filters:
  - RemoveRequestHeader=X-Request-Id
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .removeRequestHeader("X-Request-Id")
        )
        .uri("lb://user-service")
)
7.1.5 移除响应头过滤器(RemoveResponseHeader)

移除响应头过滤器用于移除响应头:

yaml 复制代码
filters:
  - RemoveResponseHeader=X-Response-Id
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .removeResponseHeader("X-Response-Id")
        )
        .uri("lb://user-service")
)
7.1.6 请求参数过滤器(AddRequestParameter)

请求参数过滤器用于添加请求参数:

yaml 复制代码
filters:
  - AddRequestParameter=version, v1
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .addRequestParameter("version", "v1")
        )
        .uri("lb://user-service")
)
7.1.7 前缀过滤器(PrefixPath)

前缀过滤器用于在请求路径前添加前缀:

yaml 复制代码
filters:
  - PrefixPath=/api
java 复制代码
.route("user-service-route", r -> r
        .path("/users/**")
        .filters(f -> f
                .prefixPath("/api")
        )
        .uri("lb://user-service")
)
7.1.8 移除前缀过滤器(StripPrefix)

移除前缀过滤器用于移除请求路径的前缀:

yaml 复制代码
filters:
  - StripPrefix=1
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .stripPrefix(1)
        )
        .uri("lb://user-service")
)
7.1.9 重试过滤器(Retry)

重试过滤器用于在请求失败时重试:

yaml 复制代码
filters:
  - name: Retry
    args:
      retries: 3
      statuses: BAD_GATEWAY
      methods: GET
      backoff:
        firstBackoff: 100ms
        maxBackoff: 1s
        factor: 2
        basedOnPreviousValue: false
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .retry(retryConfig -> {
                    retryConfig.setRetries(3);
                    retryConfig.setStatuses(HttpStatus.BAD_GATEWAY);
                    retryConfig.setMethods(HttpMethod.GET);
                    retryConfig.setBackoff(100, 1000, 2, false);
                })
        )
        .uri("lb://user-service")
)
7.1.10 限流过滤器(RequestRateLimiter)

限流过滤器用于限制请求速率:

yaml 复制代码
filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 10
      redis-rate-limiter.burstCapacity: 20
      redis-rate-limiter.requestedTokens: 1
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .requestRateLimiter(config -> {
                    config.setRateLimiter(redisRateLimiter());
                    config.setReplenishRate(10);
                    config.setBurstCapacity(20);
                    config.setRequestedTokens(1);
                })
        )
        .uri("lb://user-service")
)

7.2 自定义GatewayFilter

可以通过实现GatewayFilterFactory接口来自定义GatewayFilter:

java 复制代码
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

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

    private final AtomicInteger counter = new AtomicInteger(0);

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

    public static class Config {
        private String message;

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("message");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 前置处理
            System.out.println("CustomGatewayFilter: " + config.getMessage());
            exchange.getAttributes().put("requestCount", counter.incrementAndGet());
            
            // 调用下一个过滤器
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 后置处理
                Integer requestCount = exchange.getAttributes().get("requestCount");
                System.out.println("Request count: " + requestCount);
            }));
        };
    }
}

使用自定义GatewayFilter:

yaml 复制代码
filters:
  - Custom=Hello World
java 复制代码
.route("user-service-route", r -> r
        .path("/api/users/**")
        .filters(f -> f
                .filter(new CustomGatewayFilterFactory().apply(config -> {
                    config.setMessage("Hello World");
                    return config;
                }))
        )
        .uri("lb://user-service")
)

7.3 全局过滤器

全局过滤器应用于所有路由,可以通过实现GlobalFilter接口来创建全局过滤器:

java 复制代码
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 前置处理
        System.out.println("CustomGlobalFilter前置处理");
        
        // 调用下一个过滤器
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 后置处理
            System.out.println("CustomGlobalFilter后置处理");
        }));
    }

    @Override
    public int getOrder() {
        // 过滤器顺序,数值越小优先级越高
        return 0;
    }
}

8. 限流功能

Spring Cloud Gateway支持限流功能,可以通过集成Redis实现令牌桶算法的限流。

8.1 添加依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    <version>2.6.8</version>
</dependency>

8.2 配置Redis

yaml 复制代码
spring:
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0

8.3 配置限流

8.3.1 基于请求路径的限流
yaml 复制代码
routes:
  - id: user-service-route
    uri: lb://user-service
    predicates:
      - Path=/api/users/**
    filters:
      - name: RequestRateLimiter
        args:
          redis-rate-limiter.replenishRate: 10  # 每秒允许的请求数
          redis-rate-limiter.burstCapacity: 20  # 令牌桶的容量
          redis-rate-limiter.requestedTokens: 1  # 每个请求需要的令牌数
8.3.2 基于用户的限流
java 复制代码
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

@Configuration
public class RateLimiterConfig {

    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }
}
yaml 复制代码
routes:
  - id: user-service-route
    uri: lb://user-service
    predicates:
      - Path=/api/users/**
    filters:
      - name: RequestRateLimiter
        args:
          redis-rate-limiter.replenishRate: 10
          redis-rate-limiter.burstCapacity: 20
          redis-rate-limiter.requestedTokens: 1
          key-resolver: "#{@userKeyResolver}"
8.3.3 基于IP地址的限流
java 复制代码
@Bean
public KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
yaml 复制代码
routes:
  - id: user-service-route
    uri: lb://user-service
    predicates:
      - Path=/api/users/**
    filters:
      - name: RequestRateLimiter
        args:
          redis-rate-limiter.replenishRate: 10
          redis-rate-limiter.burstCapacity: 20
          redis-rate-limiter.requestedTokens: 1
          key-resolver: "#{@ipKeyResolver}"

8.4 自定义限流算法

可以通过实现RateLimiter接口来自定义限流算法:

java 复制代码
import org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import reactor.core.publisher.Mono;

@Component
public class CustomRateLimiter extends AbstractRateLimiter<CustomRateLimiter.Config> implements RateLimiter<CustomRateLimiter.Config> {

    private final Map<String, AtomicInteger> counters = new ConcurrentHashMap<>();

    public CustomRateLimiter() {
        super(Config.class, "custom-rate-limiter");
    }

    public static class Config {
        private int limit;

        public int getLimit() {
            return limit;
        }

        public void setLimit(int limit) {
            this.limit = limit;
        }
    }

    @Override
    public Mono<Response> isAllowed(String routeId, String key) {
        return Mono.fromSupplier(() -> {
            // 自定义限流逻辑
            AtomicInteger counter = counters.computeIfAbsent(key, k -> new AtomicInteger(0));
            int count = counter.incrementAndGet();
            
            // 每秒重置计数器
            if (count == 1) {
                new Thread(() -> {
                    try {
                        Thread.sleep(1000);
                        counters.remove(key);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
            
            boolean allowed = count <= getConfig().getLimit();
            return new Response(allowed, Map.of("remaining", Math.max(0, getConfig().getLimit() - count)));
        });
    }
}

使用自定义限流算法:

yaml 复制代码
routes:
  - id: user-service-route
    uri: lb://user-service
    predicates:
      - Path=/api/users/**
    filters:
      - name: RequestRateLimiter
        args:
          rate-limiter: "#{@customRateLimiter}"
          custom-rate-limiter.limit: 10

9. 熔断功能

Spring Cloud Gateway支持熔断功能,可以与Hystrix、Resilience4j等熔断组件集成。

9.1 与Resilience4j集成

9.1.1 添加依赖
xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
    <version>2.1.3</version>
</dependency>
9.1.2 配置熔断
yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - name: CircuitBreaker
              args:
                name: userServiceCircuitBreaker
                fallbackUri: forward:/fallback/users

resilience4j:
  circuitbreaker:
    instances:
      userServiceCircuitBreaker:
        registerHealthIndicator: true
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        permittedNumberOfCallsInHalfOpenState: 3
        automaticTransitionFromOpenToHalfOpenEnabled: true
        waitDurationInOpenState: 5s
        failureRateThreshold: 50
        eventConsumerBufferSize: 10
9.1.3 实现降级处理
java 复制代码
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FallbackController {

    @RequestMapping("/fallback/users")
    public String fallbackUsers() {
        return "User service is unavailable, please try again later.";
    }
}

9.2 与Hystrix集成

9.2.1 添加依赖
xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>
9.2.2 配置熔断
yaml 复制代码
spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - Hystrix=fallbackCommand

# Hystrix配置
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
    fallbackCommand:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 2000
9.2.3 实现降级处理
java 复制代码
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.HystrixCommands;
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;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration
@EnableHystrix
public class HystrixConfig {

    @Bean
    public RouterFunction<ServerResponse> fallbackRoute() {
        return route(path("/fallback/users"), request -> 
                ServerResponse.ok().body(Mono.just("User service is unavailable, please try again later."), String.class));
    }
}

10. 安全性

Spring Cloud Gateway可以与Spring Security无缝集成,实现安全认证和授权。

10.1 添加依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.6.8</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
    <version>5.6.3</version>
</dependency>

10.2 配置Spring Security

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
                .authorizeExchange(exchanges -> exchanges
                        // 允许访问健康检查和指标端点
                        .pathMatchers("/actuator/health", "/actuator/info").permitAll()
                        // 其他请求需要认证
                        .anyExchange().authenticated()
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        // 使用JWT认证
                        .jwt(jwt -> jwt
                                .jwtDecoder(jwtDecoder())
                        )
                );
        
        return http.build();
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        // 配置JWT解码器
        return NimbusJwtDecoder.withJwkSetUri("http://localhost:8080/.well-known/jwks.json").build();
    }
}

10.3 配置CORS

yaml 复制代码
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true
java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowedOrigins(Arrays.asList("*"));
        corsConfig.setAllowedMethods(Arrays.asList("*"));
        corsConfig.setAllowedHeaders(Arrays.asList("*"));
        corsConfig.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);
        
        return new CorsWebFilter(source);
    }
}

11. 监控和可观测性

Spring Cloud Gateway提供了丰富的监控指标和日志支持,可以通过Spring Boot Actuator监控网关的运行状态。

11.1 启用Actuator

yaml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
  metrics:
    tags:
      application: ${spring.application.name}

11.2 监控指标

Spring Cloud Gateway提供了以下监控指标:

  • gateway.requests:请求计数和持续时间
  • gateway.routes:路由计数
  • gateway.filter:过滤器执行计数和持续时间

可以通过以下端点访问监控指标:

  • /actuator/health:健康检查
  • /actuator/metrics:所有指标
  • /actuator/metrics/gateway.requests:请求指标
  • /actuator/metrics/gateway.routes:路由指标
  • /actuator/metrics/gateway.filter:过滤器指标
  • /actuator/prometheus:Prometheus格式的指标

11.3 日志配置

yaml 复制代码
logging:
  level:
    org.springframework.cloud.gateway: DEBUG
    org.springframework.web.reactive: DEBUG
    reactor.netty: DEBUG

11.4 分布式追踪

Spring Cloud Gateway可以与Sleuth和Zipkin集成,实现分布式追踪:

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>3.1.3</version>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    <version>3.1.3</version>
</dependency>
yaml 复制代码
spring:
  zipkin:
    base-url: http://localhost:9411/
    enabled: true
  sleuth:
    sampler:
      probability: 1.0

12. 最佳实践

12.1 路由设计

  • 使用清晰的路由ID:路由ID应该具有描述性,便于识别和调试
  • 合理划分路由:根据业务模块划分路由,避免路由过于复杂
  • 使用服务发现:优先使用服务发现(如Eureka、Consul),避免硬编码服务地址
  • 使用负载均衡:使用负载均衡(如Ribbon),提高系统的可用性和性能

12.2 过滤器使用

  • 合理使用过滤器:只添加必要的过滤器,避免过滤器链过长影响性能
  • 使用全局过滤器:对于所有路由都需要的功能,使用全局过滤器
  • 使用局部过滤器:对于特定路由需要的功能,使用局部过滤器
  • 自定义过滤器:根据业务需求自定义过滤器,实现特定功能

12.3 性能优化

  • 启用连接池:启用HTTP连接池,减少TCP连接建立的开销
  • 启用压缩:启用请求和响应压缩,减少网络传输量
  • 使用缓存:对于频繁访问的静态资源,使用缓存减少后端服务压力
  • 优化路由匹配:使用精确的路由匹配,避免模糊匹配影响性能
  • 使用异步处理:使用异步处理,提高系统的并发处理能力

12.4 安全性

  • 启用SSL/TLS:加密网络通信,保护数据安全
  • 使用认证和授权:对所有请求进行认证和授权,防止未授权访问
  • 启用CORS:配置合理的CORS策略,防止跨域攻击
  • 使用JWT:使用JWT进行身份认证,避免会话管理的复杂性
  • 定期更新依赖:定期更新依赖,修复安全漏洞

12.5 监控和可观测性

  • 启用Actuator:启用Actuator,监控系统的运行状态
  • 配置日志:配置合理的日志级别,便于调试和问题定位
  • 使用分布式追踪:使用分布式追踪(如Sleuth和Zipkin),追踪请求的完整路径
  • 使用APM工具:使用APM工具(如SkyWalking、Pinpoint),实现系统的全链路监控

13. 总结

Spring Cloud Gateway是Spring Cloud生态系统中的新一代API网关组件,它基于Spring Boot 2.x和Spring WebFlux构建,提供了高性能、响应式的网关服务。

Spring Cloud Gateway具有以下主要特点:

  • 响应式编程模型:基于WebFlux构建,支持高并发、低延迟的响应式编程
  • 动态路由:支持动态配置和更新路由规则
  • 强大的过滤器链:提供丰富的内置过滤器和自定义过滤器支持
  • 限流和熔断:集成Redis实现限流,支持与Hystrix、Resilience4j等熔断组件集成
  • 安全认证:与Spring Security无缝集成,支持OAuth2、JWT等认证方式
  • 监控和可观测性:提供详细的监控指标和日志支持
  • 与Spring Cloud生态集成:与Eureka、Consul、Nacos等服务注册中心无缝集成

通过本文的学习,读者可以了解Spring Cloud Gateway的核心概念、架构设计、安装配置、路由规则、过滤器、限流熔断等功能,并能够使用Spring Cloud Gateway构建高性能、可靠的API网关服务。

在实际项目中,Spring Cloud Gateway可以帮助开发者实现系统的统一入口管理、请求路由、负载均衡、安全认证、限流熔断等功能,提高系统的可用性、安全性和性能。随着微服务架构的广泛应用,Spring Cloud Gateway将成为构建现代微服务系统的重要组件。

相关推荐
likuolei2 小时前
XML DOM 节点类型
xml·java·服务器
ZHE|张恒3 小时前
Spring Bean 生命周期
java·spring
q***38515 小时前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
小白学大数据5 小时前
Python爬虫伪装策略:如何模拟浏览器正常访问JSP站点
java·开发语言·爬虫·python
程序员西西6 小时前
SpringBoot接口安全:APIKey保护指南
java·spring boot·计算机·程序员·编程·编程开发
summer_west_fish7 小时前
单体VS微服务:架构选择实战指南
java·微服务·架构
v***8577 小时前
Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
java·ubuntu·centos
烤麻辣烫7 小时前
黑马程序员大事件后端概览(表现效果升级版)
java·开发语言·学习·spring·intellij-idea
q***96587 小时前
Spring总结(上)
java·spring·rpc