内置断言
名称 | 功能 | 使用 |
---|---|---|
Path | 请求路径匹配 | - Path=/red/{segment},/blue/{segment} |
Query | 请求参数匹配 | - Query=tenantId,123456 |
Method | 请求类型匹配 | - Method=GET,POST |
After | 某个时间之后 | - After=1996-10-12T10:12:00.789-07:00[America/Denver] |
Befor | 某个时间之前 | - Befor=1996-10-12T10:12:00.789-07:00[America/Denver] |
Between | 时间段内 | - Between=开始时间,结束时间 |
Cookie | cookie中包含 | - Cookie=chocolate, 某个正则表达式 |
Header | header中包含 | - Header=X-Request-Id, 某个正则表达式 |
Host | 请求的host值 | - Host=.somehost.org,.anotherhost.org |
RemoteAddr | 请求的远程地址 | - RemoteAddr=192.168.1.1/24 |
Weight | 路由转发权重 | - Weight=group1, 2 |
XForwardedRemoteAddr | 许根据 X-Forwarded-For的 HTTP Header 对请求进行过滤 | - XForwardedRemoteAddr=192.168.1.1/24 |
自定义断言
@Component
public class CustomRoutePredicateFactory extends AbstractRoutePredicateFactory<CustomRoutePredicateFactory.Config> {
public QueryParamRoutePredicateFactory() { super(Config.class); }
@Override
public List<String> shortcutFieldOrder() { return Arrays.asList("param", "regexp"); }
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
boolean flage = flase;
// 业务逻辑
return flag;
};
}
public static class Config {
private String param;
private java.util.regex.Pattern regexp;
public Config(String param, String regexp) {
this.param = param;
this.regexp = java.util.regex.Pattern.compile(regexp);
}
}
}
路由配置
spring:
cloud:
gateway:
routes:
- id: my-route-id-1
predicates:
- Path=/order-service/**
- Custom=param,lcl
uri: http://127.0.0.1:7777
filters:
- StripPrefix=1
父级:
public interface GlobalFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
public interface Ordered {
// 值越小,优先级越高
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
// 值越大,优先级越低
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}
内置全局过滤器:
名称 | 排序 | 说明 |
---|---|---|
RemoveCachedBodyFilter | MIN_VALUE | 清除上下文中的body缓存,配合AdaptCachedBodyGlobalFilter使用 |
AdaptCachedBodyGlobalFilter | MIN_VALUE + 1000 | 在请求处理的不同阶段,缓存请求和响应的body |
NettyWriteResponseFilter | -1 | 将使用Netty发起的服务的响应数据返回到客户端 |
WebClientWriteResponseFilter | -1 | 将使用WebClient发起的服务的响应数据返回到客户端 |
ForwardPathFilter | 0 | 用来处理Forward URI,对应ForwardRoutingFilter来转发请求 |
GatewayMetricsFilter | 0 | 收集网关的基本性能指标数据,例如请求的数量、响应时间等 |
RouteToRequestUrlFilter | 1000 | 根据请求的URL将请求路由到适当的目标微服务 |
WeightCalculatorWebFilter | 10000 + 1 | 是动态调整路由权重 |
ReactiveLoadBalancerClientFilter | 10150 | 负载均衡和运行状况检查 |
LoadBalancerServiceInstanceCookieFilter | 10150 + 1 | 处理负载均衡服务实例的cookie |
WebsocketRoutingFilter | MAX_VALUE- 1 | 处理WebSocket协议的请求转发 |
ForwardRoutingFilter | MAX_VALUE | 处理forward协议 的请求,将ForwardPathFilter构建的新的Request发送给DispatcherHandler处理 |
NettyRoutingFilter | MAX_VALUE | 使用 Netty 作为客户端进行HTTP请求处理路由决策 |
WebClientHttpRoutingFilter | MAX_VALUE | 使用WebClient 作为客户端进行HTTP请求处理路由决策【构建反应式应用和服务】 |
自定义全局过滤器:注册即生效与所有路由
@Slf4j @Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info(">>>>> 自定义全局过滤器执行,排序号=10");
// TODO 业务逻辑
return chain.filter(exchange);
}
@Override
public int getOrder() { return 10; }
}
父级:
public abstract class AbstractGatewayFilterFactory<C> extends AbstractConfigurable<C> implements GatewayFilterFactory<C>, ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@SuppressWarnings("unchecked")
public AbstractGatewayFilterFactory() { super((Class<C>) Object.class); }
public AbstractGatewayFilterFactory(Class<C> configClass) { super(configClass); }
protected ApplicationEventPublisher getPublisher() { return this.publisher; }
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { this.publisher = publisher; }
public static class NameConfig {
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
}
public interface Ordered {
// 值越小,优先级越高
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
// 值越大,优先级越低
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
int getOrder();
}
内置网关过滤器工厂:
名称 | 说明 |
---|---|
OrderedGatewayFilter | 管理过滤器链中的过滤器执行顺序 |
RequestRateLimiter | 请求限流 |
AddRequestHeader | 添加请求头 |
AddRequestHeadersIfNotPresent | 添加请求头(只在 header 信息不存在的情况) |
RemoveRequestHeader | 删除请求头 |
SetRequestHeader | 修改请求头 |
SetRequestHostHeader | 替换请求的host |
SecureHeaders | 在HTTP响应中添加安全相关的HTTP头部,以增强应用的安全性 |
PreserveHostHeader | 保留原始请求的Host头信息 |
AddRequestParameter | 添加请求参数 |
RemoveRequestParameter | 删除请求参数 |
MapRequestHeader | 修改请求中的头部信息 |
RequestHeaderSize | 限制通过网关的请求头的大小 |
ModifyRequestBody | 重写请求体(这个过滤器只能通过使用Java DSL来配置) |
CacheRequestBody | 缓存响应体(请求体只能被读取一次) |
名称 | 说明 |
AddResponseHeader | 添加响应头 |
RemoveResponseHeader | 删除响应头 |
SetResponseHeader | 修改响应头 |
RewriteResponseHeader | 重写响应头中的值 |
RewriteLocationResponseHeader | 修改Location响应头 |
DedupeResponseHeader | 响应头去重 |
RemoveJsonAttributesResponseBody | 移除响应体中的某些JSON属性 |
ModifyResponseBody | 重写响应体(这个过滤器只能通过使用Java DSL来配置。) |
LocalResponseCache | 缓存响应数据,后续相同的请求,网关可以直接从缓存中获取响应,无需再次发送请求 |
名称 | 说明 |
PrefixPath | 为匹配成功的路由添加请求路径前缀 |
StripPrefix | 去掉部分URL路径 |
SetPath | 设置请求的路径 |
RewritePath | 重写请求的路径 |
RedirectTo | 将客户端的请求重定向到另一个URL |
名称 | 说明 |
SetStatus | 修改HTTP响应的状态码 |
CircuitBreaker | 熔断。防止服务雪崩,通过断路机制来保护系统免受突发流量或服务故障的影响 |
FallbackHeaders | 在请求失败时,向客户端返回一个自定义的响应头 |
JSONToGRPCFilter | 将一个JSON格式的请求转换为gRPC请求 |
SaveSession | 在请求处理过程中保存会话信息 |
Retry | 提供重试机制,帮助处理网络延迟、服务暂时不可用等临时性问题 |
TokenRelay | 在请求转发过程中,将原始请求中的Token信息传递给下游服务 |
自定义网关过滤器:注册后,还需在路由中配置使用
@Slf4j @Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> implements Ordered {
public CustomGatewayFilterFactory() { super(Config.class); }
@Override
public List<String> shortcutFieldOrder() { return Arrays.asList("name", "age"); }
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
log.info(">>>>> 自定义网关过滤器工厂执行:order=10,config={}", config);
// TODO 业务逻辑
return chain.filter(exchange);
};
}
@Override
public int getOrder() { return 10; }
@Data
public static class Config {
private String name;
private String age;
}
}
路由配置
spring:
cloud:
gateway:
routes:
- id: my-route-id-1
predicates:
- Path=/order-service/**
uri: http://127.0.0.1:7777
filters:
- StripPrefix=1
- AddRequestParameter=tenantId, 123456
- Custom=张三,18 # 配置自定义网关过滤器
添加Nacos依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
dependencies>
配置Nacos,设置 spring.cloud.gateway.discovery.locator.enabled=true 并确保 DiscoveryClient 实现
spring:
cloud:
# Nacos 配置
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
enabled: true # 让 gateway 可以配合 nacos,自动路由微服务,并实现负责均衡
routes:
- id: nacos-service-route
predicates:
- Path=/order-service/**
uri: lb://ORDER-SERVICE # lb是负载均衡,后面跟服务名称【uri=lb://TEST_SERVICE】
filters:
- StripPrefix=1 # 内置过滤器-StripPrefix:表示截断路径前缀。如果请求的路径为/order-service/order/1,则路径会修改为/order/1】
通过配置内置网关过滤器工厂RequestRateLimiterGatewayFilterFactory
spring:
cloud:
gateway:
routes:
- id: nacos-service-route
predicates:
- Path=/order-service/**
uri: lb://ORDER-SERVICE
filters:
- StripPrefix=1
- name: RequestRateLimiter # 内置限流过滤器-RequestRateLimiterGatewayFilterFactory:这个Filter依赖于Redis实现的令牌桶限流
args:
key-resolver: '#{@uriKeyResolver}' # 限流维度实现类:可以根据ip,uri,设备号,用户id等进行限流,这里使用uriKeyResolver对url进行限流
redis-rate-limiter.replenishRate: 1 # 每秒填充平均速率,相当于QPS
redis-rate-limiter.burstCapacity: 1 # 限流容量
redis-rate-limiter.requestedTokens: 1 # 每个请求需要的令牌数
不同的限流维度Bean
@Configuration
public class RateConfig {
/** Uri维度限流方法 */
@Bean
public KeyResolver uriKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
}
}