springcloud中网关gateway总结

在 Spring Cloud 微服务架构中,网关(Gateway)是客户端与微服务集群之间的 "统一入口",负责处理跨服务的共性问题。以下从作用、实现原理、核心配置(含限流、鉴权详解)三方面展开说明。

一、网关的核心作用

微服务拆分后,客户端需与多个服务直接交互,会面临地址管理、权限混乱、流量失控等问题。网关的核心作用是统一管控这些共性问题,具体包括:
  1. 路由转发:根据请求路径、参数等规则,将请求转发到对应的微服务(如将/user/**转发到用户服务,/order/**转发到订单服务)。
  2. 负载均衡:集成服务发现(如 Nacos、Eureka),自动将请求分发到同一服务的不同实例,实现负载均衡。
  3. 统一鉴权:拦截所有请求,验证 Token、权限等,避免每个服务重复实现鉴权逻辑。
  4. 流量控制(限流):限制单位时间内的请求量,防止服务被高并发击垮。
  5. 熔断降级:当下游服务故障时,返回预设的降级响应(如 "服务暂时不可用"),避免级联失败。
  6. 日志监控:统一记录请求日志(路径、耗时、状态等),便于问题排查。
  7. 协议转换:如将 HTTP 请求转换为 RPC(如 Dubbo)请求,适配不同服务的通信协议。

二、实现原理(以 Spring Cloud Gateway 为例)

Spring Cloud Gateway 是目前主流的网关组件(替代了 Zuul),基于Netty 响应式编程(非阻塞),性能优于传统的 Servlet 阻塞式架构。其核心原理依赖三个核心概念:路由(Route)、断言(Predicate)、过滤器(Filter)。

1. 核心概念

  • 路由(Route):网关的基本单元,定义 "请求如何转发"。由三部分组成:
    • id:路由唯一标识;
    • uri:目标服务地址(如lb://user-servicelb表示负载均衡,user-service是服务名);
    • predicates:断言集合(判断请求是否匹配当前路由);
    • filters:过滤器集合(对请求 / 响应进行加工)。
  • 断言(Predicate):本质是 "条件判断规则",用于匹配请求的属性(如路径、方法、请求头、时间等)。例如:
    • Path=/user/**:匹配路径以/user/开头的请求;
    • Method=GET:只匹配 GET 请求;
    • Header=token, \d+:匹配请求头token的值为数字的请求。
  • 过滤器(Filter):对请求 / 响应进行拦截和处理,分为两类:
    • GatewayFilter:针对特定路由的过滤器(如某个路由的路径重写);
    • GlobalFilter:全局过滤器(对所有路由生效,如鉴权、日志)。

2. 工作流程

客户端请求到达网关后,处理流程如下:
  1. 请求接入:客户端请求被 Netty 服务器接收,进入网关处理流程。
  2. 路由匹配:网关通过断言(Predicate)判断请求是否匹配某个路由(如路径/user/1匹配Path=/user/**的路由)。
  3. 过滤器链执行:
    • 先执行 "前置过滤器"(如鉴权、限流),若不通过则直接返回错误(如 401 无权限);
    • 若通过,将请求转发到uri指定的目标服务(通过负载均衡选择具体实例)。
  4. 响应处理:目标服务返回响应后,执行 "后置过滤器"(如日志记录、响应头修改),最终将响应返回给客户端。

三、核心配置详解

Spring Cloud Gateway 的配置可通过application.yaml(或application.properties)和代码两种方式实现,以下重点说明常用配置。

1. 基础路由配置(必选)

通过配置文件定义路由规则,示例:
spring:
  cloud:
    gateway:
      routes:
        # 路由1:用户服务
        - id: user-service-route  # 唯一标识
          uri: lb://user-service  # 目标服务(lb表示负载均衡,依赖服务发现)
          predicates:  # 断言规则(满足所有条件才匹配)
            - Path=/user/**  # 匹配路径以/user/开头的请求
            - Method=GET,POST  # 只允许GET/POST方法
          filters:  # 路由专属过滤器
            - RewritePath=/user/(?<segment>.*), /api/user/$\{segment}  # 路径重写:/user/1 → /api/user/1
        # 路由2:订单服务
        - id: order-service-route
          uri: lb://order-service
          predicates:
            - Path=/order/**
 
  • 说明:uri: lb://服务名需配合服务发现组件(如 Nacos),网关会自动从注册中心获取服务实例地址并实现负载均衡。

2. 限流配置(核心)

限流用于保护服务不被高并发击垮,Spring Cloud Gateway 基于令牌桶算法实现,需结合 Redis 存储令牌桶状态(依赖spring-boot-starter-data-redis-reactive)。
步骤 1:引入依赖
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
步骤 2:配置限流规则
需定义限流键(KeyResolver)(如按 IP、用户 ID、接口路径限流),并在路由中启用限流过滤器。
  • 示例 1:按 IP 限流(同一 IP 单位时间内最多 N 个请求)① 定义 KeyResolver(获取客户端 IP): 
    @Configuration
    public class GatewayConfig {
        // 按IP限流的键解析器
        @Bean
        public KeyResolver ipKeyResolver() {
            return exchange -> Mono.just(
                // 获取客户端IP(注意:若有反向代理需处理X-Forwarded-For头)
                exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
            );
        }
    }
    
     
     
    ② 在路由中配置限流过滤器:
    spring:
      cloud:
        gateway:
          routes:
            - id: user-service-route
              uri: lb://user-service
              predicates:
                - Path=/user/**
              filters:
                - name: RequestRateLimiter  # 启用限流过滤器
                  args:
                    redis-rate-limiter.replenishRate: 10  # 令牌填充速率(每秒10个令牌)
                    redis-rate-limiter.burstCapacity: 20  # 令牌桶容量(最多存20个令牌)
                    key-resolver: "#{@ipKeyResolver}"  # 引用上面定义的IP限流键
    
     
     
    说明:replenishRate=10表示每秒生成 10 个令牌,burstCapacity=20表示最多允许突发 20 个请求(超过则限流,返回 429 状态码)。
  • 示例 2:按接口路径限流(同一接口单位时间内最多 N 个请求)① 定义按路径的 KeyResolver:
    @Bean
    public KeyResolver pathKeyResolver() {
        return exchange -> Mono.just(
            exchange.getRequest().getPath().toString()  // 以请求路径作为限流键
        );
    }
    
     
     
    ② 路由中引用pathKeyResolver即可。

3. 鉴权配置(核心)

鉴权是网关的重要职责,通常基于 Token(如 JWT)实现:客户端请求时携带 Token,网关验证 Token 有效性,无效则拒绝访问。
实现方式:自定义 GlobalFilter
全局过滤器对所有路由生效,步骤如下:
  1. 自定义鉴权过滤器:
@Component
@Order(-1)  // 优先级(数字越小越先执行,需在路由转发前执行)
public class AuthFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. 获取请求头中的Token
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        // 2. 验证Token(忽略登录接口等白名单)
        String path = exchange.getRequest().getPath().toString();
        if (path.contains("/login")) {  // 登录接口放行
            return chain.filter(exchange);
        }
        if (token == null || !validateToken(token)) {  // Token无效
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);  // 401
            return exchange.getResponse().setComplete();  // 直接返回
        }
        
        // 3. Token有效:解析用户信息,放入请求头供下游服务使用
        String userId = parseUserIdFromToken(token);  // 从Token中解析用户ID
        ServerHttpRequest request = exchange.getRequest()
                .mutate()
                .header("X-User-Id", userId)  // 向下游传递用户ID
                .build();
        exchange = exchange.mutate().request(request).build();
        
        // 4. 继续执行过滤器链(转发请求)
        return chain.filter(exchange);
    }

    // 验证Token有效性(实际中需调用认证服务或解析JWT签名)
    private boolean validateToken(String token) {
        // 示例:简化逻辑,实际需校验签名、过期时间等
        return token.startsWith("valid_");
    }

    // 从Token中解析用户ID
    private String parseUserIdFromToken(String token) {
        return token.split("_")[1];  // 示例:valid_123 → 123
    }
}
 
  1. 配置白名单:
     
    实际场景中,除了登录接口,可能还有健康检查、公开接口等需要放行,可在过滤器中通过路径匹配实现,或通过配置文件定义白名单:
    gateway:
      auth:
        white-list: /login,/health,/public/**  # 白名单路径
    
     
     
    过滤器中读取白名单并判断是否放行。

4. 其他常用配置

  • 跨域配置:解决前端跨域问题(浏览器限制不同域名的请求):
    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':  # 对所有路径生效
                allowed-origins: "https://example.com"  # 允许的源(*表示所有,生产环境不建议)
                allowed-methods: GET,POST,PUT,DELETE  # 允许的方法
                allowed-headers: "*"  # 允许的请求头
                allow-credentials: true  # 允许携带Cookie
    
     
     
  • 熔断降级:结合 Resilience4j,当下游服务超时 / 异常时返回降级响应:
    spring:
      cloud:
        gateway:
          routes:
            - id: user-service-route
              uri: lb://user-service
              predicates:
                - Path=/user/**
              filters:
                - name: CircuitBreaker  # 启用熔断过滤器
                  args:
                    name: userServiceCircuitBreaker  # 熔断实例名
                    fallbackUri: forward:/fallback/user  # 降级路径(网关内的接口)
    
     
     
    需额外定义/fallback/user接口,返回降级响应(如{"code":503,"msg":"服务暂时不可用"})。

总结

Spring Cloud 网关通过路由转发连接客户端与微服务,通过断言匹配请求,通过过滤器实现限流、鉴权等共性功能。核心配置中,限流依赖 Redis 和令牌桶算法,鉴权依赖自定义全局过滤器验证 Token,二者共同保障微服务的安全性和稳定性。
posted @ 2025-10-23 10:02  郭慕荣  阅读(19)  评论(0)    收藏  举报