一、整体架构图
客户端 → Nginx (负载均衡) → Spring Cloud Gateway → 微服务集群
↑
服务注册中心 (Eureka/Nacos)
二、详细架构流程图
让我们通过一个具体的例子来说明整个请求流程:客户端调用 api/userService/userInfo 获取用户信息。
Spring Cloud Gateway 请求调用用户服务的完整流程示例
让我们通过一个具体的例子来说明整个请求流程:客户端调用 api/userService/userInfo
获取用户信息。
三、Nginx 配置示例
upstream gateway {
server gateway1.example.com:8080;
server gateway2.example.com:8080;
keepalive 64;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://gateway;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 长连接优化
proxy_http_version 1.1;
proxy_set_header Connection "";
# 超时设置
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
# 健康检查
location /health {
proxy_pass http://gateway/actuator/health;
}
}
四、Spring Cloud Gateway 最佳实践
1. 基础配置示例
application.yml
spring:
cloud:
gateway:
httpclient:
pool:
max-idle-time: 60000
max-connections: 1000
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY,INTERNAL_SERVER_ERROR
methods: GET,POST
2. 安全实践
JWT 认证过滤器
@Component
public class JwtAuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (StringUtils.isEmpty(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
try {
// 验证token逻辑
Claims claims = Jwts.parser()
.setSigningKey("secret")
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody();
// 将用户信息添加到header
exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.build();
return chain.filter(exchange);
} catch (Exception e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
}
}
3. 熔断降级配置
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/fallback/order
Fallback 控制器
@RestController
@RequestMapping("/fallback")
public class FallbackController {
@GetMapping("/order")
public Mono<ResponseEntity<String>> orderFallback() {
return Mono.just(ResponseEntity
.status(HttpStatus.SERVICE_UNAVAILABLE)
.body("Order Service is unavailable. Please try again later."));
}
}
4. 监控与指标
management:
endpoints:
web:
exposure:
include: health,info,gateway,metrics
endpoint:
health:
show-details: always
gateway:
enabled: true
五、高级实践代码示例
1. 动态路由配置
@Configuration
public class DynamicRouteConfig {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
public void addRoute(RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
}
public void deleteRoute(String routeId) {
routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
}
}
2. 灰度发布过滤器
@Component
public class GrayReleaseFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String version = exchange.getRequest().getHeaders().getFirst("X-Version");
if ("v2".equals(version)) {
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-Gray", "true")
.build();
return chain.filter(exchange.mutate().request(request).build());
}
return chain.filter(exchange);
}
}
3. 请求日志过滤器
@Component
@Order(-1)
public class RequestLogFilter implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(RequestLogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
String path = exchange.getRequest().getPath().toString();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long duration = System.currentTimeMillis() - startTime;
int status = exchange.getResponse().getStatusCode() != null ?
exchange.getResponse().getStatusCode().value() : 500;
log.info("Request {} - Status: {} - Time: {}ms",
path, status, duration);
}));
}
}
六、部署建议
-
高可用部署:
- 至少部署2个Gateway实例
- 使用Nginx做负载均衡
-
性能优化:
spring: cloud: gateway: httpclient: pool: max-connections: 1000 acquire-timeout: 5000 max-idle-time: 60000
-
健康检查:
- 配置Kubernetes/ECS的健康检查端点:
/actuator/health
- 设置合理的检查间隔
- 配置Kubernetes/ECS的健康检查端点:
-
日志收集:
- 集成ELK或类似日志系统
- 记录关键请求信息
七、完整请求流程图
1. 客户端发起请求
客户端发送请求到Nginx入口:
GET http://api.yourdomain.com/api/userService/userInfo
Authorization: Bearer xxxxxx
2. Nginx反向代理
Nginx配置将请求转发到Gateway集群:
location /api/ {
proxy_pass http://gateway_cluster/;
# 其他代理配置...
}
3. Gateway接收请求并路由
Gateway路由配置 (application.yml):
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service # lb表示从服务注册中心获取负载均衡地址
predicates:
- Path=/api/userService/**
filters:
- StripPrefix=2 # 去掉/api/userService前缀
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
4. Gateway处理流程
- 路由匹配:Gateway发现请求路径
/api/userService/userInfo
匹配Path=/api/userService/**
断言 - 服务发现:通过
lb://user-service
从Eureka/Nacos获取用户服务的实际地址(如http://192.168.1.10:8081
) - 过滤器处理:
StripPrefix=2
过滤器将路径变为/userInfo
- 限流过滤器检查请求频率
- 如果有其他全局过滤器(如JWT验证)也会执行
- 转发请求:Gateway将请求转发到用户服务实例:
GET http://192.168.1.10:8081/userInfo
5. 用户服务处理
用户服务接收到请求:
@RestController
@RequestMapping("/userInfo")
public class UserController {
@GetMapping
public ResponseEntity<UserInfo> getUserInfo(@RequestHeader("X-User-Id") String userId) {
// 业务逻辑处理
UserInfo user = userService.getUserById(userId);
return ResponseEntity.ok(user);
}
}
6. 响应返回路径
响应沿原路返回:
用户服务 → Gateway → Nginx → 客户端
关键组件代码示例
1. Gateway全局过滤器(添加用户ID)
@Component
public class AuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (StringUtils.isEmpty(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 模拟JWT解析
String userId = parseUserIdFromToken(token);
// 将用户ID添加到header
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", userId)
.build();
return chain.filter(exchange.mutate().request(request).build());
}
private String parseUserIdFromToken(String token) {
// 实际项目中使用JWT库解析
return "12345"; // 模拟返回用户ID
}
}
2. 用户服务Controller
@RestController
public class UserController {
@GetMapping("/userInfo")
public Map<String, Object> getUserInfo(
@RequestHeader("X-User-Id") String userId,
HttpServletRequest request) {
// 获取实际请求的IP(从Gateway转发)
String clientIp = request.getHeader("X-Forwarded-For");
return Map.of(
"userId", userId,
"username", "user_" + userId,
"email", userId + "@example.com",
"requestFrom", clientIp,
"servicePort", request.getServerPort()
);
}
}
3. 测试请求示例
请求:
curl -X GET "http://api.yourdomain.com/api/userService/userInfo" \
-H "Authorization: Bearer mock_token_123"
响应:
{
"userId": "12345",
"username": "user_12345",
"email": "12345@example.com",
"requestFrom": "客户端真实IP",
"servicePort": "8081"
}
- 统一入口:所有API请求都通过Gateway进入,简化客户端调用
- 服务发现:自动发现服务实例,无需硬编码IP
- 负载均衡:多个用户服务实例时自动均衡负载
- 横切关注点:
- 认证/授权在Gateway统一处理
- 限流、熔断等保护措施
- 日志记录和监控
- 路径转换:对外暴露友好API,内部服务可使用不同路径
通过这样的架构,你的微服务系统可以获得更好的可维护性、扩展性和安全性。
七、常见问题解决方案
- CORS问题:
@Bean
public CorsWebFilter corsFilter() {
return new CorsWebFilter(source -> {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(3600L);
return config;
});
}
- 大文件上传:
spring:
webflux:
max-in-memory-size: 10MB
- 请求超时:
spring:
cloud:
gateway:
httpclient:
response-timeout: 10s
connect-timeout: 2s
通过以上配置和实践,Spring Cloud Gateway 可以成为微服务架构中强大的API网关,提供路由、安全、监控等关键功能。