gateway
官网
地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html
如果包含了gateway的starter但不希望启用网关,设置:
spring.cloud.gateway.enabled=false
此外gateway必须在springboot的环境中运行,不能在servlet的war环境中运行。
网关(gateway)
-
Gateway是基于异步非阻塞模型上进行开发的
-
为了提升网关性能,SpringCloud Gateway是使用WebFlux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架。
SpringCloud Gateway的目标提供统一的方式且基于Filter链的方式提供了网关的基本功能,例如:安全,监控/指标和限流。
作用
- 反向代理
- 鉴权
- 流量监控
- 熔断
- 日志监控
特性
- 动态路由:能够匹配任何请求属性。
- 可以对路由指定Predicate(断言)和Filter(过滤器)。
- 集成Hystrix的断路器功能。
- 集成Spring Cloud服务功能。
- 易于编写的Predicate(断言)和Filter(过滤器)。
- 请求限流功能。
- 支持路径重写。
Spring Cloud Gateway与Zuul的区别
Zuul 1.x,是一个基于阻塞I/O的APIy。
Zuul 1.x基于Servlet2.5使用阻塞架构它不支持任何长连接
pring Cloud Gateway,是一个基于非阻塞我的API
Spring Cloud Gateway支持WebSocket,并且与Spring紧密集成拥有更好的开发体验
三大核心概念
Route路由
对URL请求进行路由转发。
是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
Predicate断言
这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。如果请求与断言相匹配则进行路由。
Filter过滤
这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
predicate就是我们的匹配条件;而filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。
工作流程
客户端(Web,浏览器,小程序,APP)向 Spring Cloud Gateway 发出请求。然后在 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。
过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。
Filter在"pre"类型的过滤器可以做参数校验,权限校验,流量监控,日志输出,协议转换等。
在“post”类型的过滤器中可以做相应内容,响应头的修改,日志的输出,流量监控等有着非常重要的作用。
在spring Cloud 的配置
Spring Cloud Gateway 网关路由有两种配置方式:
- 在配置文件 yml 中配置
- 通过@Bean自定义 RouteLocator,在启动主类 Application 中配置
Maven依赖导入
<!-- gateway依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Spring Cloud Gateway 不需要引入 web 模块。原因:它是使用 netty+webflux 实现的。
yml配置文件
server:
port: 8080
spring:
application:
name: gateway-8080
cloud:
gateway:
routes:
#路由的ID,没有固定规则,但要求唯一,建议配合服务名
- id: bilibili
# 匹配后提供服务的路由地址
uri: https://www.bilibili.com
# 断言,路径相匹配的进行路由
predicates:
- Path=/guochuang/**
各字段含义如下:
id:我们自定义的路由 ID,保持唯一
uri:目标服务器
predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
上面这段配置的意思是,配置了一个 id 为 gateway-service 的路由规则,当访问地址 http://localhost:8080/guochuang时会自动转发到地址:https://www.bilibili.com/guochuang。
代码配置路由
package org.hydrakyoufeng.sch.gateway;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
// 路由构造器
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 设置路径
routes.route("bilibili", r -> {
return r.path("/guochuang").uri("https://www.bilibili.com");
});
return routes.build();
}
}
可结合eureka注册中心使用,eureka的使用详情可以看我上一篇文章
路由规则
predica介绍
网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。
通过时间匹配
After:在这个时间之后的请求转发到目标地址。
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- After=2019-01-01T00:00:00+08:00[Asia/Shanghai]
而Before相反
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Before=2019-01-01T00:00:00+08:00[Asia/Shanghai]
Between:在这个时间段内会请求转发到目标地址
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Between=2019-01-01T00:00:00+08:00[Asia/Shanghai], 2019-07-01T00:00:00+08:00[Asia/Shanghai]
通过Header属性匹配
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Header=X-Request-Id, \d+
通过Cookie匹配
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Cookie=sessionId, test
通过Host匹配
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Host=**.baidu.com
通过请求方式匹配
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Method=GET
通过请求路径匹配
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: http://ityouknow.com
order: 0
predicates:
- Path=/foo/{segment}
通过请求参数匹配
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Query=smile
通过请求ip地址进行匹配
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
RemoteAddr=192.168.1.1/24
组合使用
server:
port: 9090
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: gateway-service
uri: https://www.baidu.com
order: 0
predicates:
- Host=**.foo.org
- Path=/headers
- Method=GET
- Header=X-Request-Id, \d+
- Query=foo, ba.
- Query=baz
- Cookie=chocolate, ch.p
- After=2018-01-20T06:06:06+08:00[Asia/Shanghai]