一、为什么需要网关?
1、什么是网关?
传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。那有了网关之后,能够起到怎样的改善呢?
网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务,所以,使用网关的好处在于:
简化客户端的工作。 网关将微服务封装起来后,客户端只需同网关交互,而不必调用各个不同服务;
降低函数间的耦合度。 一旦服务接口修改,只需修改网关的路由策略,不必修改每个调用该函数的客户端,从而减少了程序间的耦合性
解放开发人员把精力专注于业务逻辑的实现。 由网关统一实现服务路由(灰度与ABTest)、负载均衡、访问控制、流控熔断降级等非业务相关功能,而不需要每个服务 API 实现时都去考虑
但是 API 网关也存在不足之处,在微服务这种去中心化的架构中,网关又成了一个中心点或瓶颈点,它增加了一个我们必须开发、部署和维护的高可用组件。正是由于这个原因,在网关设计时必须考虑即使 API 网关宕机也不要影响到服务的调用和运行,所以需要对网关的响应结果有数据缓存能力,通过返回缓存数据或默认数据屏蔽后端服务的失败。
在服务的调用方式上面,网关也有一定的要求,API 网关最好是支持 I/O 异步、同步非阻塞的,如果服务是同步阻塞调用,可以理解为微服务模块之间是没有彻底解耦的,即如果A依赖B提供的API,如果B提供的服务不可用将直接影响到A不可用,除非同步服务调用在API网关层或客户端做了相应的缓存。
因此为了彻底解耦,在微服务调用上更建议选择异步方式进行。而对于 API 网关需要通过底层多个细粒度的 API 组合的场景,推荐采用响应式编程模型进行而不是传统的异步回调方法组合代码,其原因除了采用回调方式导致的代码混乱外,还有就是对于 API 组合本身可能存在并行或先后调用,对于采用回调方式往往很难控制。
2、服务网关的基本功能
![](https://i-blog.csdnimg.cn/blog_migrate/42d2dce96dca2d44eef4a338c65c388d.png)
3、流量网关与服务网关的区别
![](https://i-blog.csdnimg.cn/blog_migrate/857a671a26afb4e47baabc0e99bd4fd1.png)
流量网关和服务网关在系统整体架构中所处的位置如上图所示,流量网关(如Nignx)是指提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控等。
而微服务网关(如Spring Cloud Gateway)是指与业务紧耦合的、提供单个业务域级别的策略,如服务治理、身份认证等。也就是说,流量网关负责南北向流量调度及安全防护,微服务网关负责东西向流量调度及服务治理。
二、服务网关的部署
1、主流网关的对比与选型
![](https://i-blog.csdnimg.cn/blog_migrate/9f77dcb26c3d1ce5b501638aae9b2c78.png)
Kong 网关:Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑
Zuul1.x 网关:Zuul 1.0 的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况
gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud 生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。
Zuul 2.x:性能与 gateway 差不多,基于非阻塞的,支持长连接,但 SpringCloud 没有集成 zuul2 的计划,并且 Netflix 相关组件都宣布进入维护期,前景未知。
综上,gateway 网关更加适合 SpringCloud 项目,而从发展趋势上看,gateway 替代 zuul 也是必然的。
Spring Cloud Gateway 核心概念
1、Route
Route 是网关的基础元素,表示一个具体的路由信息。当请求到达网关时,由 Gateway Handler Mapping 通过 断言 进行路由匹配,就是 Mapping , 当断言为真时,匹配的路由。
路由有以下几个部分组成:
id :路由的标识,唯一,区别于其他路由;
uri :目标 uri ,客户端的请求被最终转发到的目的地址;
order :多个 route 之间的排序,数值越小,匹配优先级越高;
predicate :断言,就是路由的匹配条件,其作用是进行条件判断,当断言为真时,才会执行真正的路由;
filter :过滤器,可以在请求发出的前后进行一些业务上的处理。
2、Predicate
Predicate 来自于 Java8 的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
Predicate 可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。Spring Cloud Gateway 内置了许多 Predict,这些 Predict 的源码在 org.springframework.cloud.gateway.handler.predicate 包中
3、Filter
Filter 是 Gateway 中的过滤器,可以在请求发出的前后做一些业务上的处理。
将以上三个核心点连起来看,当用户发出请求到达 Gateway ,Gateway 会通过一些匹配条件,定位到真正的服务节点,并在这个转发过程前后,进行一些及细化控制。其中 Predicate 就是我们匹配的条件,而 Filter 可以理解为一个拦截器,有了这两个点,再加上目标 uri ,就可以实现一个具体的路由了。
如何使用?
1、引入Gateway依赖
![](https://i-blog.csdnimg.cn/blog_migrate/d266613b04a08d18abbf0dfc5758cf44.png)
2、添加路由规则
![](https://i-blog.csdnimg.cn/blog_migrate/46f71db85e4a41a9af908b59ed6ad748.png)
第一条路由规则:断言为 Query=url,qq,表示当请求路径中包含 url=qq,则跳转到http://www.qq.com
第二条路由规则:当请求路径中包含 url=baidu,则跳转到http://www.baidu.com