← 返回首页

Java API网关详解

📂 java ⏱ 3 min 433 words

Java API网关详解

什么是API网关

API网关是微服务架构的统一入口,负责路由转发、认证鉴权、限流熔断、日志监控等横切关注点。

Spring Cloud Gateway

核心概念

┌─────────────────────────────────────────┐
│              Gateway                     │
├─────────────────────────────────────────┤
│  Route (路由):转发规则                  │
│  Predicate (断言):匹配条件              │
│  Filter (过滤器):请求/响应处理          │
└─────────────────────────────────────────┘

依赖配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

路由配置

spring:
  cloud:
    gateway:
      routes:
        # 用户服务
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=0

        # 订单服务
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
            - Method=GET,POST
          filters:
            - AddRequestHeader=X-Source, gateway

        # 多条件匹配
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/products/**
            - Host=api.example.com
            - After=2024-01-01T00:00:00+08:00

过滤器

内置过滤器

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - AddRequestHeader=X-Request-Id, 12345
            - AddRequestParameter=name, value
            - AddResponseHeader=X-Response-Time, 100ms
            - PrefixPath=/v2
            - Retry=3
            - CircuitBreaker=name=myCircuitBreaker
            - RequestRateLimiter=replenishRate=10,burstCapacity=20

自定义过滤器

@Component
public class LoggingFilter implements GatewayFilter, Ordered {
    private static final Logger log = LoggerFactory.getLogger(LoggingFilter.class);

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        long start = System.currentTimeMillis();
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        String method = request.getMethod().name();
        String remoteAddr = request.getRemoteAddress().getAddress().getHostAddress();

        log.info("请求开始: {} {} from {}", method, path, remoteAddr);

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            long cost = System.currentTimeMillis() - start;
            HttpStatus statusCode = exchange.getResponse().getStatusCode();
            log.info("请求完成: {} {} status={} cost={}ms",
                method, path, statusCode, cost);
        }));
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

// 全局过滤器
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");

        if (token == null || !validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 解析用户信息并传递给下游服务
        String userId = parseUserId(token);
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-User-Id", userId)
            .build();

        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return -100;
    }

    private boolean validateToken(String token) { return true; }
    private String parseUserId(String token) { return "123"; }
}

限流配置

@Configuration
public class RateLimiterConfig {
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(
            exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
        );
    }
}

# 限流配置
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                key-resolver: "#{@userKeyResolver}"

跨域配置

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

异常处理

@Component
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        ServerHttpResponse response = exchange.getResponse();

        if (response.isCommitted()) {
            return Mono.error(ex);
        }

        log.error("网关异常: {}", ex.getMessage(), ex);

        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);

        String body = String.format(
            "{\"code\":500,\"message\":\"%s\"}",
            ex.getMessage() != null ? ex.getMessage() : "网关错误"
        );

        DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
        return response.writeWith(Mono.just(buffer));
    }
}

动态路由

@Component
public class DynamicRouteService implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher publisher;

    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void addRoute(RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    public void deleteRoute(String routeId) {
        routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
        publisher.publishEvent(new RefreshRoutesEvent(this));
    }
}

总结

Spring Cloud Gateway是Spring Cloud生态中的官方网关方案,基于WebFlux实现,支持路由、过滤器、限流、跨域等功能。合理配置网关可以有效保护后端服务。