API网关设计
API网关设计
什么是API网关
API网关是微服务架构中的关键组件,它作为客户端与后端服务之间的单一入口点,负责请求路由、协议转换、认证授权、限流熔断等功能。
核心功能
请求路由
将客户端请求路由到相应的后端服务。
# Spring Cloud Gateway路由配置
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
filters:
- StripPrefix=1
认证授权
在网关层统一处理认证和授权,避免在每个服务中重复实现。
// JWT认证过滤器
@Component
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {
private final JwtTokenValidator tokenValidator;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return unauthorized(exchange);
}
String token = authHeader.substring(7);
if (!tokenValidator.validate(token)) {
return unauthorized(exchange);
}
Claims claims = tokenValidator.parseToken(token);
// 将用户信息添加到请求头,传递给下游服务
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Roles", claims.get("roles", String.class))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
private Mono<Void> unauthorized(ServerWebExchange exchange) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1; // 高优先级
}
}
// 授权过滤器
@Component
public class AuthorizationFilter implements GlobalFilter, Ordered {
private final AuthorizationService authorizationService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
String roles = exchange.getRequest().getHeaders().getFirst("X-User-Roles");
String path = exchange.getRequest().getPath().value();
String method = exchange.getRequest().getMethod().name();
if (!authorizationService.isAuthorized(userId, roles, path, method)) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0; // 在认证过滤器之后执行
}
}
限流熔断
防止后端服务过载,保护系统稳定性。
// 限流配置
@Configuration
public class RateLimitConfig {
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders().getFirst("X-User-Id")
);
}
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.requestRateLimiter(config -> config
.setKeyResolver(userKeyResolver())
.setRateLimiter(redisRateLimiter())
)
)
.uri("lb://user-service"))
.build();
}
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(10, 20, 1); // 10 requests/sec, burst capacity 20
}
}
// 熔断器配置
@Configuration
public class CircuitBreakerConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("order-service", r -> r
.path("/api/orders/**")
.filters(f -> f
.circuitBreaker(config -> config
.setName("orderService")
.setFallbackUri("forward:/fallback/orders")
)
)
.uri("lb://order-service"))
.build();
}
}
// 熔断降级处理
@RestController
public class FallbackController {
@RequestMapping("/fallback/orders")
public ResponseEntity<String> ordersFallback() {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body("Order service is currently unavailable. Please try again later.");
}
}
协议转换
支持不同协议之间的转换,如HTTP到gRPC。
// HTTP到gRPC转换
@Component
public class GrpcConversionFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().value();
if (path.startsWith("/grpc/")) {
// 将HTTP请求转换为gRPC调用
return handleGrpcRequest(exchange, chain);
}
return chain.filter(exchange);
}
private Mono<Void> handleGrpcRequest(ServerWebExchange exchange, GatewayFilterChain chain) {
// 实现HTTP到gRPC的转换逻辑
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 1;
}
}
API聚合
将多个后端服务的响应聚合为一个响应,减少客户端请求次数。
// API聚合控制器
@RestController
@RequestMapping("/api/aggregated")
public class AggregatedController {
private final UserClient userClient;
private final OrderClient orderClient;
private final ProductClient productClient;
@GetMapping("/user/{userId}/dashboard")
public ResponseEntity<UserDashboard> getUserDashboard(@PathVariable Long userId) {
// 并行调用多个服务
CompletableFuture<UserDto> userFuture = CompletableFuture.supplyAsync(
() -> userClient.getUser(userId)
);
CompletableFuture<List<OrderDto>> ordersFuture = CompletableFuture.supplyAsync(
() -> orderClient.getOrdersByUser(userId)
);
CompletableFuture<List<ProductDto>> productsFuture = CompletableFuture.supplyAsync(
() -> productClient.getRecommendedProducts(userId)
);
// 等待所有响应
CompletableFuture.allOf(userFuture, ordersFuture, productsFuture).join();
// 聚合结果
UserDashboard dashboard = new UserDashboard();
dashboard.setUser(userFuture.join());
dashboard.setRecentOrders(ordersFuture.join());
dashboard.setRecommendedProducts(productsFuture.join());
return ResponseEntity.ok(dashboard);
}
}
常用技术选型
Spring Cloud Gateway
// Spring Cloud Gateway配置
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.stripPrefix(1)
.addRequestHeader("X-Request-Source", "gateway")
.retry(config -> config
.setRetries(3)
.setBackoff(Duration.ofMillis(100), Duration.ofSeconds(1), 2, true)
)
)
.uri("lb://user-service"))
.build();
}
}
Kong
# Kong路由配置
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rate-limiting
config:
minute: 100
policy: local
---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: jwt
config:
uri_param_names: jwt
header_names: Authorization
---
apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: user-service
spec:
routes:
- paths:
- /api/users
strip_path: true
plugins:
- name: rate-limiting
- name: jwt
Zuul
// Zuul路由配置
@Configuration
public class ZuulConfig {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://user-service"))
.build();
}
}
// Zuul过滤器
@Component
public class PreFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 添加请求头
ctx.addZuulRequestHeader("X-Request-Source", "zuul");
return null;
}
}
高可用设计
集群部署
# Kubernetes部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
replicas: 3
spec:
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
spec:
containers:
- name: api-gateway
image: api-gateway:latest
ports:
- containerPort: 8080
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: api-gateway-service
spec:
selector:
app: api-gateway
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
最佳实践
- 单一入口:所有外部请求都通过API网关进入
- 最小权限:网关只暴露必要的API,不暴露内部服务细节
- 统一认证:在网关层统一处理认证授权
- 限流熔断:保护后端服务免受过载
- 监控日志:记录所有请求和响应,便于调试和审计
- 版本管理:支持API版本管理,确保向后兼容
- 缓存策略:对频繁访问的数据进行缓存
- 错误处理:统一错误响应格式,提供有用的错误信息