https://mp.weixin.qq.com/s/f2hepLraaqUgRKqq9ZKKsQ
基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术, 目标是替代 Netflix ZUUL
千万不要依赖 引入spring-boot-starter-web包
简单来说就是 把符合 {匹配规则} 的请求 发给 {服务地址} ,请求与返回 期间经过 {过滤处理}
Spring Gateway支持两种方式提供路由服务,其一是配置文件启用,其二则是通过代码达到目的
spring:
application:
name: xxxx
cloud:
# 配置 路由网关
gateway:
# 配置路由规则
routes:
- id: {路由id}
uri: {服务地址}
predicates:
- {匹配规则}
filters:
- {过滤处理}
spring:
application:
name: xxxx
cloud:
# 配置 服务注册发现
nacos:
discovery:
server-addr: 127.0.0.1:8848
# 配置 路由网关
gateway:
# 设置与服务注册发现组件结合,这样可以采用服务名的路由策略
discovery:
locator:
enabled: true
# 配置路由规则
routes:
# 路由 ID,不同的 id 有不同的功能
- id: activity-route
# 要使用nacos服务注册中心的服务:lb://{注册的服务名}
uri: lb://activity
# 路由断言Factories
predicates:
- Path=/activity/**
- id: search-route
uri: http://localhost:8081
predicates:
- Method=GET
filters:
# 转发请求时去掉1级前缀
- StripPrefix=1
表示 以/activity/**
开头的请求 转发到 lb://activity
服务
Gateway默认转发是全路径的,
设置 StripPrefix =1 表示从二级url路径转发,即http://ip:port/1/2/3
会转发到http://ip:port/2/3
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
//一个 .route 就是一个路由规则
.route(r -> r.path("/activity/**")
.filters(f -> f.stripPrefix(1).filter(new TestGetWayFilter()).addResponseHeader("X-Response-Default-Foo", "Default-Bar"))
.uri("lb://activity")
.order(0) //如果路由需要有顺序匹配的,需要使用 order 方法 值越小优先匹配
.id("activity-route")
)
.route(r -> r.path("/activity/**")
//使用
.filters(f -> f.filter(new myFilter()))
.uri("lb://activity")
.order(0) //如果路由需要有顺序匹配的,需要使用 order 方法 值越小优先匹配
.id("activity-route")
)
.build();
}
通过 Nacos Server 和 Spring Cloud Alibaba Nacos Config 即可实现配置的动态变更,官方文档地址:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-configopen in new window
Spring会根据名称去查找对应的FilterFactory,目前支持的名称有:After、Before、Between、Cookie、Header、Host、Method、Path、Query、RemoteAddr。
predicates:
# 在该日期时间之后发生的请求都将被匹配
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
# 在该日期时间之前发生的请求都将被匹配。
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
# 在datetime1和datetime2之间的请求将被匹配
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
# 请求包含此cookie名称且正则表达式为真的将会被匹配
- Cookie=chocolate, regular expression
- Header=X-Request-Id, \d+
- Host=**.somehost.org,**.anotherhost.org
- Method=GET
- Path=/foo/{segment},/bar/{segment}
- Query=baz
- Query=foo, ba.
- RemoteAddr=192.168.1.1/24
filters:
# 转发请求时去掉1级前缀
- StripPrefix=1
# 给请求的Header中添加: X-Request-Foo, Bar
- AddRequestHeader=X-Request-Foo, Bar
# 给响应的Header中添加: X-Request-Foo, Bar
- AddResponseHeader=X-Response-Foo, Bar
实现 GlobalFilter, Ordered 接口并在类上增加 @Component 注解就可以使用过滤功能
import .......
/**
* 过滤器
*/
@Component
public class myFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().pathWithinApplication().value();
//TODO
return chain.filter(exchange);
}
/**
* 设置过滤器的执行顺序
* @return
*/
@Override
public int getOrder() {
return 1;
}
}
Spring Cloud Gateway 自带了限流过滤器,对应的接口是 RateLimiter,RateLimiter 接口只有一个实现类 RedisRateLimiter (基于 Redis + Lua 实现的限流),提供的限流功能比较简易且不易使用。
从 Sentinel 1.6.0 版本开始,Sentinel 引入了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:route 维度和自定义 API 维度。也就是说,Spring Cloud Gateway 可以结合 Sentinel 实现更强大的网关流量控制
Spring Cloud Gateway 提供了多种全局处理的方式,比较常用的一种是实现ErrorWebExceptionHandler并重写其中的handle方法。
不能用SpringBoot 的@RestControllerAdvice和 @ExceptionHandler