跳到主要内容

API 网关设计

问题

如何设计一个高性能的 API 网关?

答案

网关职责

Spring Cloud Gateway 核心

路由配置 + 自定义过滤器
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("order-service", r -> r
.path("/api/orders/**")
.filters(f -> f
.stripPrefix(1) // 去掉 /api 前缀
.requestRateLimiter(rl -> rl // 限流
.setRateLimiter(redisRateLimiter())
.setKeyResolver(userKeyResolver()))
.circuitBreaker(cb -> cb // 熔断
.setName("orderCB")
.setFallbackUri("forward:/fallback"))
)
.uri("lb://order-service")) // 负载均衡
.build();
}
}

请求聚合(BFF 模式)

网关层聚合多个后端接口
@RestController
public class AggregationController {

@GetMapping("/api/home")
public Mono<HomePageVO> homePage(@RequestHeader("X-User-Id") Long userId) {
// 并行调用多个微服务
Mono<UserInfo> user = userClient.getUser(userId);
Mono<List<Order>> orders = orderClient.getRecentOrders(userId);
Mono<List<Product>> recommend = productClient.getRecommend(userId);

return Mono.zip(user, orders, recommend)
.map(tuple -> new HomePageVO(tuple.getT1(), tuple.getT2(), tuple.getT3()));
}
}

灰度发布

根据请求头/用户标签路由到不同版本
@Component
public class GrayFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");

// 灰度用户路由到 v2 版本
if (isGrayUser(userId)) {
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-Version", "v2")
.build();
return chain.filter(exchange.mutate().request(request).build());
}
return chain.filter(exchange);
}
}

常见面试问题

Q1: 网关有什么主流选择?

答案

网关语言特点
Spring Cloud GatewayJavaSpring 生态,响应式
NginxC高性能,静态配置
KongLua/C插件丰富,声明式配置
APISIXLua高性能,动态路由

Q2: 网关如何避免成为单点瓶颈?

答案

  • 网关本身无状态,水平扩展
  • 前面加 LVS/Nginx 做四层/七层负载均衡
  • 限流、熔断保护后端服务

Q3: 网关和 BFF 的关系?

答案

  • 网关:通用功能(路由、鉴权、限流)
  • BFF:针对前端的接口聚合和数据裁剪
  • 可以在网关内实现 BFF,也可以独立部署

相关链接