Appearance
API网关
API网关是微服务架构中的关键组件,作为系统的入口点,它管理和路由所有外部客户端请求到适当的微服务。Spring Cloud提供了多种API网关实现,包括Spring Cloud Gateway和旧版的Zuul。
API网关的作用
API网关在微服务架构中扮演着重要角色,提供以下功能:
- 请求路由:将客户端请求路由到相应的微服务
- API组合:聚合多个微服务的API调用,减少客户端与服务端的通信次数
- 协议转换:支持不同协议之间的转换(如HTTP、WebSocket)
- 负载均衡:分发请求到不同的服务实例
- 认证与授权:集中处理身份验证和权限控制
- 限流与熔断:提供流量控制和服务保护机制
- 监控与日志:收集请求和响应的监控指标与日志
- 缓存:缓存常用的响应数据,减轻后端服务压力
Spring Cloud Gateway 简介
Spring Cloud Gateway是Spring Cloud官方推荐的API网关,基于Spring WebFlux构建,提供非阻塞、响应式的API网关功能。它替代了早期的Zuul网关,提供更好的性能和更丰富的功能。
核心概念
Spring Cloud Gateway有三个核心概念:
- 路由(Route):网关的基本构建块,由ID、目标URI、一系列的断言和过滤器组成
- 断言(Predicate):Java 8中的Predicate函数,用于匹配HTTP请求中的任何内容
- 过滤器(Filter):修改请求和响应的SpringWebFilter,分为Gateway Filter和Global Filter
工作流程
Spring Cloud Gateway的工作流程如下:
- 客户端发送请求到API网关
- Gateway Handler Mapping确定请求是否与路由匹配(使用断言)
- 如果匹配成功,请求发送到Gateway Web Handler
- Handler通过特定于请求的过滤器链发送请求
- 过滤器可以在请求发送到目标服务前("pre"过滤器)或接收到响应后("post"过滤器)执行逻辑
- 代理请求发送到目标微服务
- 响应返回到客户端
配置Spring Cloud Gateway
添加依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
如果需要与服务注册中心集成:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
基本配置
使用YAML配置路由:
yaml
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/users/**
filters:
- StripPrefix=1
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/orders/**
filters:
- StripPrefix=1
在上面的配置中:
id
:路由的唯一标识符uri
:目标服务地址,lb://
前缀表示使用负载均衡predicates
:断言条件,用于匹配请求filters
:过滤器,用于修改请求或响应
使用Java代码配置
除了YAML配置,还可以使用Java代码配置路由:
java
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service-route", r -> r
.path("/users/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://user-service"))
.route("order-service-route", r -> r
.path("/orders/**")
.filters(f -> f.stripPrefix(1))
.uri("lb://order-service"))
.build();
}
}
断言工厂
Spring Cloud Gateway提供了多种内置的断言工厂,用于匹配HTTP请求的各个方面:
Path:根据请求路径匹配
yamlpredicates: - Path=/users/{segment},/user/{segment}
Method:根据HTTP方法匹配
yamlpredicates: - Method=GET,POST
Header:根据请求头匹配
yamlpredicates: - Header=X-Request-Id, \d+
Query:根据查询参数匹配
yamlpredicates: - Query=name, value.*
Cookie:根据Cookie匹配
yamlpredicates: - Cookie=sessionId, \d+
Host:根据主机名匹配
yamlpredicates: - Host=**.example.org,**.example.com
Weight:基于权重的路由
yamlroutes: - id: service-v1 uri: lb://service-v1 predicates: - Path=/service/** - Weight=service,8 - id: service-v2 uri: lb://service-v2 predicates: - Path=/service/** - Weight=service,2
DateTime:根据时间匹配
yamlpredicates: - After=2023-01-01T00:00:00+08:00[Asia/Shanghai] - Before=2023-12-31T23:59:59+08:00[Asia/Shanghai] - Between=2023-01-01T00:00:00+08:00[Asia/Shanghai],2023-12-31T23:59:59+08:00[Asia/Shanghai]
过滤器工厂
Spring Cloud Gateway提供了丰富的过滤器工厂,可以修改进出网关的请求和响应:
内置过滤器
AddRequestHeader:添加请求头
yamlfilters: - AddRequestHeader=X-Request-Id, 123
AddResponseHeader:添加响应头
yamlfilters: - AddResponseHeader=X-Response-Id, 456
StripPrefix:去除请求路径前缀
yamlfilters: - StripPrefix=1 # 去除路径中的第一段
PrefixPath:添加请求路径前缀
yamlfilters: - PrefixPath=/api
RequestRateLimiter:请求限流
yamlfilters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 key-resolver: "#{@userKeyResolver}"
Retry:重试机制
yamlfilters: - name: Retry args: retries: 3 statuses: BAD_GATEWAY methods: GET,POST
CircuitBreaker:熔断器
yamlfilters: - name: CircuitBreaker args: name: myCircuitBreaker fallbackUri: forward:/fallback
RewritePath:重写请求路径
yamlfilters: - RewritePath=/users/(?<segment>.*), /user-service/$\{segment}
自定义过滤器
可以创建自定义的GatewayFilter,用于实现特定的业务逻辑:
java
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {
public CustomGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 前置处理
ServerHttpRequest request = exchange.getRequest();
// 如果配置了追加头
if (config.isAddHeader()) {
ServerHttpRequest modifiedRequest = request.mutate()
.header("X-Custom-Header", config.getHeaderValue())
.build();
exchange = exchange.mutate().request(modifiedRequest).build();
}
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> {
// 后置处理
ServerHttpResponse response = exchange.getResponse();
// 对响应做一些处理
}));
};
}
public static class Config {
private boolean addHeader;
private String headerValue;
// getter and setter
}
}
注册自定义过滤器:
java
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("custom-filter-route", r -> r
.path("/custom/**")
.filters(f -> f
.filter(new CustomGatewayFilter())
.stripPrefix(1))
.uri("lb://custom-service"))
.build();
}
全局过滤器
全局过滤器应用于所有路由,用于实现通用功能:
java
@Component
public class GlobalAuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求
ServerHttpRequest request = exchange.getRequest();
// 获取认证信息
String token = request.getHeaders().getFirst("Authorization");
// 验证token
if (token == null || !isValidToken(token)) {
// 返回401错误
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// 继续处理请求
return chain.filter(exchange);
}
@Override
public int getOrder() {
// 设置优先级
return -1; // 数字越小,优先级越高
}
private boolean isValidToken(String token) {
// 验证token的逻辑
return true; // 实际实现中需要真正验证token
}
}
高级功能
集成断路器
集成Resilience4j断路器:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
配置断路器过滤器:
yaml
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/users/**
filters:
- name: CircuitBreaker
args:
name: userServiceCircuitBreaker
fallbackUri: forward:/fallback/user-service
创建fallback处理器:
java
@RestController
@RequestMapping("/fallback")
public class FallbackController {
@GetMapping("/user-service")
public Mono<Map<String, String>> userServiceFallback() {
Map<String, String> response = new HashMap<>();
response.put("status", "error");
response.put("message", "User service is currently unavailable");
return Mono.just(response);
}
}
限流配置
使用Redis实现限流:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
配置限流器:
java
@Configuration
public class RateLimiterConfig {
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(10, 20);
}
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders().getFirst("X-User-Id") != null ?
exchange.getRequest().getHeaders().getFirst("X-User-Id") :
exchange.getRequest().getRemoteAddress().getHostName()
);
}
}
应用限流器:
yaml
spring:
cloud:
gateway:
routes:
- id: limited-route
uri: lb://user-service
predicates:
- Path=/limited/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 # 每秒允许处理的请求数
redis-rate-limiter.burstCapacity: 2 # 每秒最大处理的请求数
key-resolver: "#{@userKeyResolver}" # 用于识别限流对象的键解析器
请求体修改
如果需要修改请求体,需要使用ModifyRequestBodyGatewayFilterFactory:
java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("modify-request-body", r -> r
.path("/modify/**")
.filters(f -> f
.modifyRequestBody(
String.class,
String.class,
(exchange, s) -> Mono.just(s.toUpperCase()))
)
.uri("lb://target-service"))
.build();
}
跨域配置
配置跨域支持:
yaml
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "https://example.org"
allowedMethods:
- GET
- POST
- PUT
- DELETE
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
或者通过Java配置:
java
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("https://example.org");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
路由断言的组合
可以组合多个断言来创建复杂的路由匹配规则:
yaml
spring:
cloud:
gateway:
routes:
- id: complex-route
uri: lb://complex-service
predicates:
- Path=/complex/**
- Method=GET
- Header=X-API-Version, v1
- Query=debug, true
上面的路由只会匹配同时满足以下条件的请求:
- 路径以/complex/开头
- HTTP方法为GET
- 请求头X-API-Version的值为v1
- 查询参数debug的值为true
动态路由
Spring Cloud Gateway支持动态刷新路由,可以与Spring Cloud Config或Nacos等配置中心集成,实现路由配置的动态更新。
使用代码动态刷新路由:
java
@RestController
@RequestMapping("/routes")
public class RouteController {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private ApplicationEventPublisher publisher;
@PostMapping
public Mono<ResponseEntity<Object>> addRoute(@RequestBody RouteDefinition routeDefinition) {
return Mono.fromCallable(() -> {
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
publisher.publishEvent(new RefreshRoutesEvent(this));
return ResponseEntity.ok().build();
});
}
@DeleteMapping("/{id}")
public Mono<ResponseEntity<Object>> deleteRoute(@PathVariable String id) {
return Mono.fromCallable(() -> {
routeDefinitionWriter.delete(Mono.just(id)).subscribe();
publisher.publishEvent(new RefreshRoutesEvent(this));
return ResponseEntity.ok().build();
});
}
}
监控与日志
Actuator配置
添加Spring Boot Actuator依赖,可以暴露网关监控端点:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置Actuator端点:
yaml
management:
endpoints:
web:
exposure:
include: gateway,health,info,metrics
endpoint:
gateway:
enabled: true
health:
show-details: always
访问网关路由信息:/actuator/gateway/routes
集成Micrometer和Prometheus
添加Micrometer依赖:
xml
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
启用Prometheus端点:
yaml
management:
endpoints:
web:
exposure:
include: prometheus,health,info,metrics
metrics:
export:
prometheus:
enabled: true
访问Prometheus指标:/actuator/prometheus
请求日志
配置日志级别以查看更多请求细节:
yaml
logging:
level:
org.springframework.cloud.gateway: DEBUG
reactor.netty: DEBUG
性能优化
合理配置线程池:调整Netty工作线程数
yamlspring: reactor: netty: worker: count: 16 # 默认为CPU核心数*2
启用HTTP/2:提高性能和减少连接数
yamlserver: http2: enabled: true
启用响应式缓存:缓存常用响应
java@Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("cached-route", r -> r .path("/cache/**") .filters(f -> f .stripPrefix(1) .cache(c -> c .timeToLive(Duration.ofMinutes(10)) .cacheSize(1000))) .uri("lb://cacheable-service")) .build(); }
使用WebClient连接池:优化后端服务调用
java@Bean public WebClient webClient() { return WebClient.builder() .clientConnector(new ReactorClientHttpConnector( HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofSeconds(5)) .pool(ConnectionProvider.fixed("custom", 50, 10000)))) .build(); }
生产环境部署
高可用部署
为确保网关的高可用性,应考虑以下几点:
- 多实例部署:部署多个网关实例,搭配负载均衡器(如Nginx、HAProxy)
- 健康检查:实现健康检查端点,确保负载均衡器能够识别不健康的实例
- 会话保持:如果必要,配置会话亲和性以保持用户会话
安全配置
HTTPS配置:启用HTTPS保障传输安全
yamlserver: ssl: key-store: classpath:keystore.jks key-store-password: password key-store-type: JKS key-alias: tomcat enabled: true
安全头部:添加安全相关响应头
yamlspring: cloud: gateway: default-filters: - AddResponseHeader=X-Content-Type-Options, nosniff - AddResponseHeader=X-Frame-Options, DENY - AddResponseHeader=X-XSS-Protection, 1; mode=block
安全策略:实现合适的认证、授权策略,如OAuth2、JWT
常见问题及解决方案
路由不匹配
问题:请求没有被路由到正确的服务 解决方案:
- 检查路由配置和断言条件
- 启用DEBUG日志观察路由匹配过程
- 使用Actuator检查已注册的路由
性能问题
问题:网关性能不佳 解决方案:
- 检查后端服务响应时间
- 优化Netty线程池配置
- 使用Micrometer监控性能指标
- 考虑增加网关实例
- 实现响应缓存
内存泄漏
问题:网关服务内存持续增长 解决方案:
- 检查WebClient连接池配置
- 确保正确处理响应式流
- 使用JVM监控工具检查内存使用情况
- 设置合理的JVM内存限制
与其他组件集成
与Spring Cloud Config集成
集成配置中心,实现动态路由配置:
yaml
spring:
cloud:
config:
uri: http://config-server:8888
name: gateway
profile: ${spring.profiles.active}
与Spring Security集成
添加Spring Security依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
配置OAuth2资源服务器:
java
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.pathMatchers("/public/**").permitAll()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
与Spring Cloud Sleuth集成
添加分布式追踪支持:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
配置Sleuth和Zipkin:
yaml
spring:
sleuth:
sampler:
probability: 1.0 # 采样率,生产环境建议降低
zipkin:
base-url: http://zipkin-server:9411
总结
Spring Cloud Gateway提供了强大而灵活的API网关解决方案,通过路由、断言和过滤器的组合,可以满足各种微服务架构的需求。作为微服务架构的入口点,它不仅处理请求路由,还承担了认证、限流、监控等重要任务。
通过本文的学习,你应该能够:
- 理解API网关在微服务架构中的作用
- 掌握Spring Cloud Gateway的核心概念和工作原理
- 学会配置路由、断言和过滤器
- 实现高级功能如限流、熔断、跨域等
- 了解网关的监控、优化和生产部署最佳实践
在实际应用中,应根据系统的规模和需求,选择合适的配置,并关注性能、安全和可用性等方面,确保API网关能够高效可靠地服务于整个微服务架构。