一、为什么使用 Gateway(核心价值)
面临的原始问题:
-
硬编码问题:前端需要知道每个微服务的 IP 和端口
-
无负载均衡:无法在多个实例间分配请求
-
跨域问题:每个服务需单独处理
-
认证授权分散:每个服务重复实现登录校验
-
限流熔断复杂:需在每个服务集成
-
监控困难:请求分散,难以统一收集日志和指标
Gateway 带来的解决方案:
前端/客户端
|
Gateway(统一入口)
|
┌─────────────────────────────────┐
│路由│过滤│限流│认证│监控│缓存│转换│
└─────────────────────────────────┘
|
Nacos/注册中心
|
┌────┬────┬────┬────┐
│服务1│服务2│服务3│...│
└────┴────┴────┴────┘
二、Gateway 核心概念补充
1. 三大核心概念
-
路由(Route):转发的规则,包含ID、目标URI、断言、过滤器
-
断言(Predicate):匹配条件(如路径、时间、Cookie等)
-
过滤器(Filter):请求处理链(修改请求/响应)
2. 与 Zuul 对比
| 特性 | Gateway | Zuul 1.x |
|---|---|---|
| 模型 | 异步非阻塞 | 同步阻塞 |
| 性能 | 高 | 较低 |
| 依赖 | WebFlux | Servlet |
| 限流 | 原生支持 | 需集成 |
| 扩展性 | 强 | 一般 |
三、配置示例补充
1. 完整 application.yml 配置
server:
port: 8888
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.61.132:8848
namespace: dev
group: DEFAULT_GROUP
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
- Method=GET,POST
- After=2022-01-01T00:00:00.000+08:00
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒填充令牌数
redis-rate-limiter.burstCapacity: 20 # 令牌桶容量
- AddRequestHeader=X-Request-Gateway, spring-cloud-gateway
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
2. 常见内置断言工厂
-
Path :路径匹配
/user/** -
Method :请求方法
GET,POST -
Header:请求头包含指定值
-
Cookie:Cookie 匹配
-
Query:查询参数匹配
-
Host:主机名匹配
-
Weight:权重路由
-
RemoteAddr:IP地址匹配
-
Time:时间相关(Before, After, Between)
3. 常见内置过滤器
-
前缀处理 :
PrefixPath,StripPrefix -
请求头 :
AddRequestHeader,RemoveRequestHeader -
响应头 :
AddResponseHeader -
重试 :
Retry -
熔断 :
CircuitBreaker -
限流 :
RequestRateLimiter -
路径重写 :
RewritePath
四、代码示例补充
1. 自定义断言工厂示例
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {
public AgeRoutePredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
String ageStr = exchange.getRequest().getQueryParams().getFirst("age");
if (ageStr == null) {
return false;
}
int age = Integer.parseInt(ageStr);
return age >= config.getMinAge() && age <= config.getMaxAge();
};
}
@Data
public static class Config {
private int minAge;
private int maxAge;
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("minAge", "maxAge");
}
}
2. 自定义过滤器工厂示例
@Component
public class LogGatewayFilterFactory extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {
public LogGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
if (config.isEnabled()) {
ServerHttpRequest request = exchange.getRequest();
log.info("Gateway Log: Path={}, Method={}, Params={}",
request.getPath(),
request.getMethod(),
request.getQueryParams());
}
return chain.filter(exchange);
};
}
@Data
public static class Config {
private boolean enabled = true;
}
}
3. 全局过滤器(认证示例)
@Component
@Order(0)
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 1. 白名单路径放行
if (isWhiteList(request.getPath().toString())) {
return chain.filter(exchange);
}
// 2. 检查 token
String token = request.getHeaders().getFirst("Authorization");
if (StringUtils.isEmpty(token)) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 3. 验证 token
if (!validateToken(token)) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.FORBIDDEN);
return response.setComplete();
}
// 4. 添加用户信息到 header
ServerHttpRequest newRequest = request.mutate()
.header("X-User-Id", getUserIdFromToken(token))
.build();
return chain.filter(exchange.mutate().request(newRequest).build());
}
private boolean isWhiteList(String path) {
return path.startsWith("/api/auth/login")
|| path.startsWith("/api/public/");
}
}
五、高级功能
1. 限流配置
spring:
redis:
host: localhost
port: 6379
cloud:
gateway:
routes:
- id: rate-limit-route
uri: lb://user-service
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userKeyResolver}"
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getQueryParams().getFirst("user")
);
}
2. 熔断降级
filters:
- name: CircuitBreaker
args:
name: userServiceCB
fallbackUri: forward:/fallback/user
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY, INTERNAL_SERVER_ERROR
六、最佳实践建议
-
生产配置
# 开启 actuator 监控端点 management: endpoints: web: exposure: include: health,info,gateway -
统一异常处理
@Component public class GlobalExceptionHandler implements ErrorWebExceptionHandler { // 统一处理 Gateway 异常 } -
链路追踪
# 集成 Sleuth spring: sleuth: web: enabled: true zipkin: base-url: http://localhost:9411/ -
CORS 配置
@Bean public CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("*"); config.addAllowedMethod("*"); config.addAllowedHeader("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); }
七、常见问题
1. 与 Web 模块冲突
<!-- ❌ 错误:Gateway 不能引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ✅ 正确:使用 WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
2. 路由顺序问题
-
路由按配置顺序匹配,先匹配先执行
-
可以使用
order属性控制优先级
3. 性能调优
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5s
pool:
max-connections: 1000
acquire-timeout: 45000