一、引言:为何选择Spring Cloud Gateway?
在微服务体系中,面对数十甚至上百个服务,让客户端直接与各个服务实例通信是灾难性的。这会导致客户端代码复杂、耦合度高、安全性难以保障,且无法统一实现认证、限流、监控等功能。
第一代网关Netflix Zuul 1.x基于Servlet阻塞IO模型,在高并发场景下性能瓶颈明显。在此背景下,Spring Cloud Gateway应运而生,它具有以下核心优势:
高性能:基于WebFlux响应式编程模型(Reactive),底层使用Netty作为服务器,完美支持异步非阻塞IO,轻松应对高并发场景。
功能强大:提供丰富的路由(Route)、断言(Predicate) 和过滤器(Filter) 机制,功能可定制性极强。
生态无缝集成:与Spring Cloud生态系统(如服务发现:Eureka, Nacos;配置中心:Config, Nacos;熔断:Sentinel)无缝集成,开箱即用。
开发者友好:支持基于Java DSL或YAML的流畅API配置,符合Spring开发者的习惯。
本文将带你从零开始,深入Spring Cloud Gateway的世界。
二、核心概念深度解析
要理解Spring Cloud Gateway,必须彻底掌握其三大核心概念:路由(Route)、断言(Predicate) 和过滤器(Filter)。
路由(Route):网关最基本的组成部分。一个路由规则定义了:当一个请求满足某种条件时,应该将它转发到哪个目的地。一个路由ID、一组断言、一组过滤器和一个目标URI组成。
断言(Predicate):这是Java 8 Function Predicate的实现。它用于匹配HTTP请求中的任何内容(例如:请求头、请求参数、路径、时间等)。如果请求与所有定义的断言都匹配,则该请求会命中这条路由。
过滤器(Filter):这是Spring Framework
GatewayFilter
的实例。顾名思义,它可以在请求下发(转发)到后端服务之前(Pre) 或从后端服务返回之后(Post),对请求和响应进行修改和增强。过滤器的作用范围是特定路由。
工作流程简述:
客户端向Spring Cloud Gateway发起请求。
Gateway Handler Mapping确定请求与哪条路由匹配(即判断请求是否满足该路由的所有断言)。
请求进入过滤器链(Web Handler)。在执行所有 “Pre”过滤器逻辑后,将请求转发到后端服务(代理服务)。
后端服务处理完请求,返回响应。
响应再经过过滤器链中所有的 “Post”过滤器处理。
最终,网关将处理后的响应返回给客户端。
三、快速开始:构建你的第一个网关
我们将通过一个简单的例子,演示如何创建一个最基本的网关,它将所有以 /api/**
开头的请求转发到指定的服务。
1. 创建项目并引入依赖
使用Spring Initializr创建一个新的Spring Boot项目,添加 Spring Cloud Gateway
依赖。同时,为了演示动态路由,我们也加入服务发现Nacos Discovery
依赖(你也可以使用Eureka)。
xml
<!-- pom.xml --> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- 以Nacos为例,引入服务发现客户端 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2022.0.0.0</version> <!-- 请选择与Spring Cloud版本匹配的版本 --> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2022.0.4</version> <!-- 此处使用Spring Cloud 2022.0.4 (代号Kilburn) --> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2022.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
2. 配置文件(YAML)方式配置路由
在 application.yml
中配置一个静态路由:
yaml
server: port: 8080 # 网关端口 spring: application: name: api-gateway cloud: gateway: routes: # 路由列表 - id: user-service-route # 路由ID,唯一 uri: http://localhost:8081 # 目标服务地址(这里先写死) predicates: # 断言列表 - Path=/api/users/** # 路径匹配断言 filters: - StripPrefix=1 # 过滤器:去掉第一层前缀 `/api`,再转发。即 /api/users/1 -> /users/1 # 可以配置多个路由 - id: order-service-route uri: http://localhost:8082 predicates: - Path=/api/orders/** filters: - StripPrefix=1 # 配置Nacos注册中心(如果使用动态路由,则需要) nacos: discovery: server-addr: localhost:8848
在这个配置中,任何发送到 http://localhost:8080/api/users/xxx
的请求都会被转发到 http://localhost:8081/users/xxx
。
3. 启动并测试
依次启动Nacos、用户服务(端口8081)和这个网关应用(端口8080)。访问 http://localhost:8080/api/users/1
,网关会自动将请求代理到 http://localhost:8081/users/1
。
四、进阶实战:动态路由与过滤器
静态配置无法适应服务实例动态变化的环境。因此,动态路由是生产环境的必备能力。
1. 整合服务发现(动态路由)
只需将配置中的 uri
从写死的地址改为以 lb://
(LoadBalance) 开头的服务名,网关就会自动从注册中心(如Nacos)获取服务实例列表并进行负载均衡。
yaml
spring: cloud: gateway: routes: - id: user-service-lb-route # 动态路由 uri: lb://user-service # lb:// + 注册中心里的服务名 predicates: - Path=/api/users/** filters: - StripPrefix=1 - id: order-service-lb-route uri: lb://order-service predicates: - Path=/api/orders/** filters: - StripPrefix=1
2. 自定义全局过滤器(Global Filter)
全局过滤器作用于所有路由,常用于实现全局统一的逻辑,如认证、日志、全局限流等。
下面我们实现一个简单的JWT认证过滤器:
java
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class JwtAuthenticationFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1. 从请求头中获取token String token = exchange.getRequest().getHeaders().getFirst("Authorization"); // 2. 判断token是否存在且有效(这里简化校验逻辑) if (token == null || !token.startsWith("Bearer ")) { // 3. token无效,返回401未授权 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); // 直接返回,不再继续执行过滤器链 } // 4. (可选)解析token,将用户信息放入请求头,传递给下游服务 // String userId = parseToken(token); // exchange = exchange.mutate().request( // r -> r.header("X-User-Id", userId) // ).build(); // 5. token有效,放行,继续执行过滤器链 return chain.filter(exchange); } @Override public int getOrder() { // 过滤器的执行顺序,数值越小优先级越高 return 0; } }
3. 自定义网关过滤器(Gateway Filter)
网关过滤器作用于特定路由,功能更细化。
下面实现一个记录请求耗时的过滤器:
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 RequestTimingGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> { @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { long startTime = System.currentTimeMillis(); return chain.filter(exchange).then( Mono.fromRunnable(() -> { long duration = System.currentTimeMillis() - startTime; System.out.println("Request to: " + exchange.getRequest().getURI() + " took " + duration + "ms"); // 可以将耗时打入Metric系统,如Prometheus }) ); }; } @Override public String name() { return "RequestTiming"; // 在配置文件中使用 - RequestTiming 来启用这个过滤器 } }
在YAML配置中使用自定义过滤器:
yaml
filters: - StripPrefix=1 - name: RequestTiming # 使用自定义过滤器
五、生产环境最佳实践
高可用(HA):
部署多个网关实例,通过Nginx或F5等负载均衡器对外提供统一入口,避免单点故障。
** resilience4j 集成**:
网关作为入口,必须要有容错能力。集成Resilience4j实现熔断(Circuit Breaker)、重试(Retry) 等功能。
yaml
filters: - name: CircuitBreaker args: name: myCircuitBreaker fallbackUri: forward:/fallback/user # 熔断后的降级地址 - name: Retry args: retries: 3 series: SERVER_ERROR # 5xx错误时重试
限流(Rate Limiting):
使用基于Redis的令牌桶或漏桶算法对特定路由或API进行限流,保护下游服务。可以使用Spring Cloud Gateway自带的
RequestRateLimiter
过滤器。
CORS 配置:
在网关层统一处理跨域问题,避免每个微服务单独处理。
yaml
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowedOrigins: "*" allowedMethods: - GET - POST - PUT - DELETE
** actuator 端点与监控**:
引入
spring-boot-starter-actuator
,暴露/actuator/gateway/routes
等端点,动态查看和刷新路由。与Micrometer、Prometheus、Grafana集成,全面监控网关的各项指标(QPS、延迟、错误率等)。
六、总结
Spring Cloud Gateway凭借其响应式编程模型带来的高性能、与Spring Cloud生态的完美融合以及极其灵活的可扩展性,已经成为现代微服务架构中API网关的事实标准。
通过本文,你应当已经掌握了:
其路由、断言、过滤器三大核心概念与工作流程。
如何通过YAML和Java代码配置静态与动态路由。
如何编写全局过滤器和自定义网关过滤器来实现认证、日志等通用逻辑。
生产环境中需要关注的高可用、熔断、限流、监控等最佳实践。
网关是微服务的门面,其稳定性和性能至关重要。希望你能将本文作为起点,不断深入,构建出强大而可靠的微服务边界系统。