一. 网关的作用及背景
1.API网关的作用
- 请求路由
在我们的系统中由于同一个接口新老两套系统都在使用,我们需要根据请求上下文将请求路由到对应的接口。
- 统一鉴权
对于鉴权操作不涉及到业务逻辑,那么可以在网关层进行处理,不用下层到业务逻辑。
- 统一监控
由于网关是外部服务的入口,所以我们可以在这里监控我们想要的数据,比如入参出参,链路时间。
- 流量控制,熔断降级
对于流量控制,熔断降级非业务逻辑可以统一放到网关层。
2.GateWay产生的背景
Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关; 但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul, 那就是SpringCloud Gateway一句话:gateway是原zuul1.x版的替代 。
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。 zuul是基于Servlet的实现,属于阻塞式编程。而SpringCloudGateway则是基于Spring5中提供的WebFlux,属于响应式编程的实现,具备更好的性能
二.GateWay配置介绍
1.GateWay三大概念
- Route(路由):路由是构建网关的基本模块,它由 ID、目标 URI、一系列的断言和过滤器组成,如果断言为 true 则匹配该路由
- Predicate(断言):参考的是 Java8 中的 java.util.function.Predicate。开发人员可以匹配 HTTP 请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
- Filter(过滤):指的是 Spring 框架中 GatewayFilter 的实例,使用过滤器,可以在请求被路由之前或之后对请求进行修改。
yaml
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: service-provider # 路由标示,必须唯一
uri: lb://SERVICE-PROVIDER # 路由的目标地址;动态路由使用,lb://微服务名
predicates: # 路由断言,判断请求是否符合规则
- Path=/provider/** # 路径断言,判断路径是否是以/provider开头,如果是则符合
- id: service-consumer
uri: lb://SERVICE-CONSUMER
predicates:
- Path=/consumer/**
1.1 Route(路由)
gateway 中可以配置多个 Route
。一个 Route
由路由 id,转发的 uri,多个 Predicates
以及多个 Filters
构成。处理请求时会按优先级排序,找到第一个满足所有 Predicates
的 Route。
1.2 Predicate(断言)
Gateway中predicates配置除了Path断言工厂,还有十几个:
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点后的请求 | -- After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | -- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | -- Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含某些cookie | -- Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | -- Header=X-Request-Id, \d+ |
Host | 请求必须是访问某个host(域名) | -- Host=.somehost.org,.anotherhost.org |
Method | 请求方式必须是指定方式 | -- Method=GET,POST |
Path | 请求路径必须符合指定规则 | -- Path=/red/{segment},/blue/** |
Query | 请求参数必须包含指定参数 | -- Query=name, Jack或者- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | -- RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
1.3 Filter(过滤)
gateway提供了31种不同的内置路由过滤器工厂。常用的如:
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除有一个响应头 |
RequestRateLimiter | 限制请求的流量 |
1.2.1 添加过滤器
yaml
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: service-provider # 路由标示,必须唯一
uri: lb://SERVICE-PROVIDER # 路由的目标地址;动态路由使用,lb://微服务名
predicates: # 路由断言,判断请求是否符合规则
- Path=/provider/** # 路径断言,判断路径是否是以/provider开头,如果是则符合
- id: service-consumer
uri: lb://SERVICE-CONSUMER
predicates:
- Path=/consumer/**
filters: # 针对某个服务添加过滤器
- AddRequestHeader=name,zhangsan
default-filters: # 全局过滤器给请求添加请求头信息
- AddRequestHeader=name,zhangsan
- AddRequestHeader=age,10
1.2.2 自定义全局过滤器(鉴权)
1.2.3 gateway中过滤器的执行顺序
- 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
- GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
- 路由过滤器和defaultFilter的order由gateway指定,默认是按照声明顺序从1递增。
- 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。
三.GateWay工作原理
1.GateWay架构原理
1.拉取注册中心的服务列表
2.获取请求地址,根据routes路由规则判断匹配所拉取的服务列表
3.路由规则匹配上了某个服务列表中的服务,负载均衡转发个对应的服务
2.GateWay的内部流程
1)服务启动时:
1.服务启动时,加载配置文件中的路由配置
2.将路由配置转化为RouteDefinition (封装gateway路由属性信息的bean,即Route的bean定义)
3.RouteLocator读取RouteDefinition并将RouteDefinition 转换成Route对象( Route对象中定义并实例化了路由断言、过滤器、路由地址及路由优先级等信息 ),并提供了获取Route对象的方法
2)客户端请求到达时:
1.Netty Server监听到客户端请求,通过所有路由的路由断言,看是否匹配上路由
2.匹配上路由,封装具体路由的Handler(将路由的一些信息封装到ServerWebExchange对象中),并将对应的过滤器链加入到Handler中
3.拿到具体路由的执行Handler后,执行过滤器链,并通过路由信息转发请求到对应的服务
RoutePredicateHandlerMapping的执行顺序
通过路由定位器获取全部路由(RouteLocator)
通过路由的谓语(Predicate)过滤掉不可用的路由信息
查找到路由信息后将路由信息设置当上下文环境中(GATEWAY_ROUTE_ATTR)
返回gatway自定的webhandler(FilteringWebHandler)