简介
https://mp.weixin.qq.com/s/f2hepLraaqUgRKqq9ZKKsQ
基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术, 目标是替代 Netflix ZUUL
千万不要依赖 引入spring-boot-starter-web包
- 客户端向 Spring Cloud Gateway 发出请求。
- 路由判断 :在 Gateway Handler Mapping 中找到与请求相匹配的路由,
- 请求过滤:将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链对请求进行拦截和修改
- 服务处理:请求发送到我们实际的服务执行业务逻辑
- 响应过滤:后端处理完结果后,返回给 Gateway 的过滤器再次做处理
- 然后返回。
简单来说就是 把符合 {匹配规则} 的请求 发给 {服务地址} ,请求与返回 期间经过 {过滤处理}
routes 路由服务
Spring Gateway支持两种方式提供路由服务,其一是配置文件启用,其二则是通过代码达到目的
spring:
application:
name: xxxx
cloud:
# 配置 路由网关
gateway:
# 配置路由规则
routes:
- id: {路由id}
uri: {服务地址}
predicates:
- {匹配规则}
filters:
- {过滤处理}
1. 配置文件方式
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
2. Java DSL方式
@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 注册中心
Spring Cloud Gateway可以从注册中心获取服务的元数据(例如服务名称、路径等),然后根据这些信息自动生成路由规则
通过 Nacos Server 和 Spring Cloud Alibaba Nacos Config 即可实现配置的动态变更,官方文档地址:https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-configopen in new window
predicates 路由断言
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
过滤器
- 分类
- 请求 Pre 类型
参数校验、权限校验、流量监控、日志输出以及协议转换等操作 - 响应 Post 类型
修改响应内容或响应头、日志输出、流量监控等。 - 全局 过滤器 GlobalFilter
用作负载均衡 - 局部 过滤器 GatewayFilter
- 请求 Pre 类型
filters 过滤功能
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