您现在的位置是:首页 >其他 >Spring Cloud Gateway使用及原理解析网站首页其他
Spring Cloud Gateway使用及原理解析
文章目录
前言
随着人Zuul2的不断跳票,Spring官方推出高性能网关Spring Cloud Gateway,使用Netty通信,reactor反应式框架编程。本文就介绍了该网关的基础内容以及进阶使用。讲解版本3.1.4对应SpringCloud版本2021.0.5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.4</version>
</dependency>
一、路由(Route)
Route主要作用就是做请求的转发,而在转发前可以对路由进行断言(判断请求是否被该路由处理)、过滤。
1.定义(RouteDefinition)
一个路由至少需要定义一个uri和一个断言,例如:定义一个处理所有请求以/web开头的请求
#lb://开头代表是服务负载均衡转发请求,如果是转发到指定地址也可以写成http://localhost:8081
spring.cloud.gateway.routes[0].uri=lb://web
#Path表示使用的是PathRoutePredicateFactory生成的GatewayPredicate,处理以/web开头的所有请求
spring.cloud.gateway.routes[0].predicates[0]=Path=/web/**
#Path表示使用的是StripPrefixGatewayFilterFactory生成的GatewayFilter,会将接口请求路径的第一部分过滤掉
# 如请求http://localhost:8802/web/user/list则实际访问的是lb://web/user/list
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
提示:断言和过滤器的定义底层解析规则都是一样的即一个名字name(String)和一组参数args(Map<String,String>),像上面的配置方式则会将Path=/web/**以逗号分隔,Path给name,/web/**给args的value,key为内部自动生成_genkey_0(数字0代表下标),如果是拦截多个路径可以写成Path=/web/**,/web2/**,则/web2/**给到args的key就为_genkey_1。这是一种快键的配置方式。我们也可以使用下面标准的配置方式
spring.cloud.gateway.routes[0].uri=lb://web
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args[patterns][0]=/web/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
2.加载(RouteDefinitionRouteLocator)
将RouteDefinition加载成Route,在1中的示例会生成一个具有一个断言一个过滤器的路由,
提示:如果定义了默认过滤器也会被加载,后面还会专门讲到
二、断言
1.内置断言
- AfterRoutePredicateFactory
- BeforeRoutePredicateFactory
- BeforeRoutePredicateFactory
- BetweenRoutePredicateFactory
- CookieRoutePredicateFactory
- HeaderRoutePredicateFactory
- HostRoutePredicateFactory
- MethodRoutePredicateFactory
- PathRoutePredicateFactory
- QueryRoutePredicateFactory
- ReadBodyRoutePredicateFactory
- RemoteAddrRoutePredicateFactory
- XForwardedRemoteAddrRoutePredicateFactory
- CloudFoundryRouteServiceRoutePredicateFactory
2.关闭/启用
#关闭After断言对应AfterRoutePredicateFactory
spring.cloud.gateway.predicate.after.enabled=false
#启用AfterRoutePredicateFactory(默认就是启用的)
spring.cloud.gateway.predicate.after.enabled=true
#关闭RemoteAddr断言对应RemoteAddrRoutePredicateFactory
spring.cloud.gateway.predicate.remote-addr.enabled=false
3.自定义
三、过滤器
有三类过滤器,其中全局过滤器GlobalFilter和默认过滤器都是对所有路由生效,区别是全局过滤器只需要定义一个实现GlobalFilter接口的bean就可以了,默认过滤器除了要定义一个实现GatewayFilterFactory接口的Bean之外还需要通过spring.cloud.gateway.default-filters配置启用,普通GatewayFilter需要在定义路由时一个个配置启用。
1.内置GlobalFilter
- RemoveCachedBodyFilter
- AdaptCachedBodyGlobalFilter
- NettyWriteResponseFilter
- GatewayMetricsFilter
- RouteToRequestUrlFilter
- ReactiveLoadBalancerClientFilter
- LoadBalancerServiceInstanceCookieFilter
- WebsocketRoutingFilter
- NettyRoutingFilter
- ForwardRoutingFilter
以上仅是默认启用的
2.默认过滤器
#配置一个默认断路过滤器
spring.cloud.gateway.default-filters[0].name=CircuitBreaker
spring.cloud.gateway.default-filters[0].args[fallbackUri]=forward:/fallback
3.GatewayFilter
- AddRequestHeaderGatewayFilterFactory
- MapRequestHeaderGatewayFilterFactory
- AddRequestParameterGatewayFilterFactory
- AddResponseHeaderGatewayFilterFactory
- ModifyRequestBodyGatewayFilterFactory
- DedupeResponseHeaderGatewayFilterFactory
- ModifyResponseBodyGatewayFilterFactory
- CacheRequestBodyGatewayFilterFactory
- PrefixPathGatewayFilterFactory
- PreserveHostHeaderGatewayFilterFactory
- RedirectToGatewayFilterFactory
- RemoveRequestHeaderGatewayFilterFactory
- RemoveRequestParameterGatewayFilterFactory
- RemoveResponseHeaderGatewayFilterFactory
- RequestRateLimiterGatewayFilterFactory
- RewritePathGatewayFilterFactory
- RetryGatewayFilterFactory
- SetPathGatewayFilterFactory
- SecureHeadersGatewayFilterFactory
- SetRequestHeaderGatewayFilterFactory
- SetRequestHostHeaderGatewayFilterFactory
- SetResponseHeaderGatewayFilterFactory
- RewriteResponseHeaderGatewayFilterFactory
- RewriteLocationResponseHeaderGatewayFilterFactory
- SetStatusGatewayFilterFactory
- SaveSessionGatewayFilterFactory
- StripPrefixGatewayFilterFactory
- RequestHeaderToRequestUriGatewayFilterFactory
- RequestSizeGatewayFilterFactory
- RequestHeaderSizeGatewayFilterFactory
三类过滤器在执行时都会被包装成GatewayFilter去执行,执行顺序是通过AnnotationAwareOrderComparator排序的即先通过是否实现Ordered接口再通过是否有@Order注解。其中需要注意的是GlobalFilter需要指定实现Ordered接口,不能使用注解@Order,github已经有许多人提了该issue
4.关闭/启用
#关闭AdaptCachedBodyGlobalFilter过滤器
spring.cloud.gateway.global-filter.adapt-cached-body.enabled=false
#关闭AddRequestHeader过滤器对应AddRequestHeaderGatewayFilterFactory
spring.cloud.gateway.filter.add-request-header.enabled=false
5.自定义
- 自定义一个全局过滤器MyGlobalFilter
@Component
public class MyGlobalFilter implements GlobalFilter{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (ObjectUtils.isEmpty(token)) {
return ServerHttpResponseUtils.failed("无token",exchange.getResponse());
}
return chain.filter(exchange);
}
}
- 自定义一个普通过滤器CustomGatewayFilterFactory
@Component
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {
private static final String REQUEST_TIME_BEGIN = "requestTimeBegin";
private static final String KEY = "withParams";
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList(KEY);
}
public CustomGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
exchange.getAttributes().put(REQUEST_TIME_BEGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(REQUEST_TIME_BEGIN);
if (startTime != null) {
StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
.append(": ")
.append(System.currentTimeMillis() - startTime)
.append("ms");
if (config.isWithParams()) {
sb.append(" params:").append(exchange.getRequest().getQueryParams());
}
System.out.println(sb);
}
})
);
};
}
public static class Config {
private boolean withParams;
public boolean isWithParams() {
return withParams;
}
public void setWithParams(boolean withParams) {
this.withParams = withParams;
}
}
}
四、熔断&限流
1.熔断
#定义一个默认配置名为base,超时时间为40s
resilience4j.timelimiter.configs.base.timeout-duration=40s
#定义微服务名web的断路超时时间为50s,若不指定时间则使用base配置中的40s
resilience4j.timelimiter.instances.web.base-config=base
resilience4j.timelimiter.instances.web.timeout-duration=50s
#配置一个默认断路过滤器
spring.cloud.gateway.default-filters[0].name=CircuitBreaker
spring.cloud.gateway.default-filters[0].args[fallbackUri]=forward:/fallback
2.限流
spring.cloud.gateway.routes[1].uri=lb://reactive-web
spring.cloud.gateway.routes[1].predicates[0]=Path=/reactive/**
spring.cloud.gateway.routes[1].predicates[1]=After=2019-04-20T17:42:47.789-07:00[America/Denver]
spring.cloud.gateway.routes[1].filters[0].name=RequestRateLimiter
spring.cloud.gateway.routes[1].filters[0].args[key-resolver]=#{@hostAddressKeyResolver}
spring.cloud.gateway.routes[1].filters[0].args[redis-rate-limiter.replenishRate]=1
spring.cloud.gateway.routes[1].filters[0].args[redis-rate-limiter.burstCapacity]=3
自定义一个key解析器
@Component
public class HostAddressKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
五、集成Nacos
1.依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.5.0</version>
</dependency>
2.路由加载
服务发现是通过DiscoveryClientRouteDefinitionLocator加载路由的,默认会加载服务注册中心中所有的服务
#排除网关自身作为路由
spring.cloud.gateway.discovery.locator.include-expression=!serviceId.equals('gateway')
总结
以上就是今天要讲的内容,本文详细介绍了Spring Cloud Gateway的使用,而Spring Cloud Gateway提供了大量能使我们快速便捷地处理路由的函数和方法。