一、微服务之困:入口的混乱

在微服务架构中,系统被拆分为数十甚至上百个独立的服务。每个服务都有自己的访问地址。这带来了一个棘手的问题:前端应用(如Web、App)或第三方调用方,到底应该和哪个服务通信?

如果让客户端直接与各个微服务通信,会面临诸多挑战:

  1. 客户端复杂性:客户端需要维护所有服务的地址,处理服务发现、负载均衡等逻辑。
  2. 认证授权冗余:每个服务都需要实现一套独立的认证和授权逻辑,重复且难以维护。
  3. 跨域问题:浏览器出于安全考虑,会限制跨域请求,需要每个服务都进行CORS配置。
  4. 协议转换困难:如果内部服务使用gRPC等协议,而外部只支持HTTP,客户端将无法直接调用。

为了解决这些问题,**API网关(API Gateway)**模式应运而生。它在所有微服务之前设立了一个统一的入口点,所有外部请求都先经过它,再由它路由到相应的后端服务。而Spring Cloud Gateway,正是Spring生态中实现API网关的首选。

二、Spring Cloud Gateway是什么?

Spring Cloud Gateway是Spring官方推出的第二代API网关框架,旨在取代老旧的Zuul 1.x。它构建于Spring 5、Spring Boot 2和Project Reactor之上,是一个完全非阻塞、响应式的网关。

如果说每个微服务是城市里的一个具体部门,那么Spring Cloud Gateway就是整个城市的**“中央交通枢纽”“总安检口”**。所有进城的请求都必须先经过这里,由它进行身份核查(认证)、安全检查(限流、熔断),然后根据请求的目的地(URL路径),将其精准地导向正确的部门(后端服务)。

三、Gateway的核心概念与工作流程

Gateway的核心逻辑非常简洁,由三个基本部分组成:

  1. 路由 (Route):网关的基本构建块。它由一个ID、一个目标URI、一组断言 (Predicate) 和一组过滤器 (Filter) 组成。如果断言为真,则匹配该路由。
  2. 断言 (Predicate):这是一个Java 8的Predicate。输入类型是Spring的ServerWebExchange。我们可以用它来匹配HTTP请求中的任何内容,例如请求头、请求参数、请求路径等。
  3. 过滤器 (Filter):这是GatewayFilter的实例,用于在请求被路由之前或之后,对请求或响应进行修改。

工作流程
一个请求到达Gateway后,Gateway Handler Mapping会根据请求信息(如路径、Host等)与路由中定义的断言进行匹配。如果找到匹配的路由,请求就会被发送到Gateway Web Handler。这个Handler会将请求通过一个过滤器链(Filter Chain),最终代理到真正的后端服务。

四、Gateway的核心功能

1. 丰富的路由断言 (Route Predicate)

Gateway内置了大量的路由断言工厂,让我们可以通过极其灵活的方式定义路由匹配规则。

  • Path断言:根据请求的URL路径进行匹配,支持Ant风格的通配符(如/users/**)。
  • Method断言:匹配HTTP请求方法(GET, POST等)。
  • Host断言:匹配请求的Host头。
  • Header/Query/Cookie断言:匹配请求头、查询参数或Cookie中是否存在某个值。
  • After/Before/Between断言:根据请求时间进行匹配,可以实现定时开启或关闭接口。

2. 强大的过滤器 (Filter)

过滤器是Gateway实现横切关注点的核心。它分为GatewayFilterGlobalFilter两种。

  • GatewayFilter:应用于单个路由或一组路由。
  • GlobalFilter:全局生效,应用于所有路由。

Gateway同样内置了丰富的过滤器工厂:

  • AddRequestHeader/AddResponseHeader:为下游请求或上游响应添加Header。
  • RewritePath:重写请求路径。例如,将/api/users/1重写为/users/1再转发给后端服务。
  • Hystrix/Sentinel:集成熔断器,为路由提供熔断降级能力。
  • RateLimiter:实现限流,保护后端服务。

3. 动态路由与服务发现

Gateway可以与注册中心(如Nacos, Eureka, Consul)无缝集成。当配置urilb://service-name时,Gateway会自动从注册中心拉取service-name对应的服务实例列表,并进行负载均衡。

五、Spring Cloud实战

在Spring Cloud项目中集成Gateway非常简单。

1. 添加Maven依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 如果需要服务发现 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2. 配置application.yml

这是Gateway最核心的配置部分,我们在这里定义所有的路由规则。

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      # 开启与服务发现组件的集成
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true # 将服务名转为小写
      
      routes:
        # 路由1:将/user/**的请求转发到user-service
        - id: user_route
          uri: lb://user-service # lb代表从注册中心进行负载均衡
          predicates:
            - Path=/user/**
          filters:
            # 转发前去掉第一级路径/user
            - StripPrefix=1 
            # 为下游请求添加一个Header
            - AddRequestHeader=X-Request-From, Gateway

        # 路由2:将/product/**的请求转发到product-service
        - id: product_route
          uri: lb://product-service
          predicates:
            - Path=/product/**
          filters:
            - StripPrefix=1
            # 为这个路由单独集成Sentinel熔断
            - name: Sentinel
              args:
                fallbackUri: forward:/fallback

# 默认的熔断回调地址
server:
  port: 8888

@RestController
public class FallbackController {
    @RequestMapping("/fallback")
    public Mono<String> fallback() {
        return Mono.just("Service is unavailable, please try again later.");
    }
}

3. 编写自定义全局过滤器

有时候,我们需要实现统一的逻辑,比如认证、日志记录等。这时可以自定义GlobalFilter

@Component
@Slf4j
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token)) {
            log.warn("Authorization token is missing.");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        // 鉴权逻辑...
        
        // 将解析出的用户信息传递给下游服务
        ServerHttpRequest modifiedRequest = exchange.getRequest().mutate()
                .header("X-User-Id", "123")
                .build();
        
        return chain.filter(exchange.mutate().request(modifiedRequest).build());
    }

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

六、总结

Spring Cloud Gateway作为现代微服务架构的入口,其重要性不言而喻。它的优势在于:

  • 性能卓越:基于WebFlux的响应式编程模型,非阻塞IO,能用更少的资源处理更高的并发。
  • 功能强大:内置丰富的断言和过滤器,配置灵活,易于扩展。
  • 无缝集成:与Spring Cloud生态(注册中心、配置中心、熔断器等)完美融合。
  • 面向未来:专为云原生和响应式应用设计。

掌握Spring Cloud Gateway,是每一位Java微服务开发者构建健壮、安全、易于管理的分布式系统的必备技能。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐