Spring Cloud 系列之 Netflix Zuul 服务网关(一)
1|0什么是 Zuul
Zuul 是从设备和网站到应用程序后端的所有请求的前门。作为边缘服务应用程序,Zuul 旨在实现动态路由,监视,弹性和安全性。Zuul 包含了对请求的路由和过滤两个最主要的功能。
Zuul 是 Netflix 开源的微服务网关,它可以和 Eureka、Ribbon、Hystrix 等组件配合使用。Zuul 的核心是一系列的过滤器,这些过滤器可以完成以下功能:
- 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求
- 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产试图
- 动态路由:动态地将请求路由到不同的后端集群
- 压力测试:逐渐增加只想集群的流量,以了解性能
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
- 静态响应处理:在边缘位置直接建立部份响应,从而避免其转发到内部集群\
- 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB(Elastic Load Balancing)使用的多样化,以及让系统的边缘更贴近系统的使用者
2|0什么是服务网关
API Gateway(APIGW / API 网关),顾名思义,是出现在系统边界上的一个面向 API 的、串行集中式的强管控服务,这里的边界是企业 IT 系统的边界,可以理解为企业级应用防火墙
,主要起到隔离外部访问与内部系统的作用
。在微服务概念的流行之前,API 网关就已经诞生了,例如银行、证券等领域常见的前置机系统,它也是解决访问认证、报文转换、访问统计等问题的。
API 网关的流行,源于近几年来移动应用与企业间互联需求的兴起。移动应用、企业互联,使得后台服务支持的对象,从以前单一的 Web 应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着微服务架构概念的提出,API 网关成为了微服务架构的一个标配组件
。
API 网关是一个服务器,是系统对外的唯一入口。API 网关封装了系统内部架构,为每个客户端提供定制的 API。所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有非业务功能。API 网关并不是微服务场景中必须的组件,如下图,不管有没有 API 网关,后端微服务都可以通过 API 很好地支持客户端的访问。
但对于服务数量众多、复杂度比较高、规模比较大的业务来说,引入 API 网关也有一系列的好处:
- 聚合接口使得服务对调用者透明,客户端与后端的耦合度降低
- 聚合后台服务,节省流量,提高性能,提升用户体验
- 提供安全、流控、过滤、缓存、计费、监控等 API 管理功能
3|0为什么要使用网关
- 单体应用:浏览器发起请求到单体应用所在的机器,应用从数据库查询数据原路返回给浏览器,对于单体应用来说是不需要网关的。
- 微服务:微服务的应用可能部署在不同机房,不同地区,不同域名下。此时客户端(浏览器/手机/软件工具)想要请求对应的服务,都需要知道机器的具体 IP 或者域名 URL,当微服务实例众多时,这是非常难以记忆的,对于客户端来说也太复杂难以维护。此时就有了网关,客户端相关的请求直接发送到网关,由网关根据请求标识解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就全部交由网关来操作了。
总结
如果让客户端直接与各个微服务交互:
- 客户端会多次请求不同的微服务,增加了客户端的复杂性
- 存在跨域请求,在一定场景下处理相对复杂
- 身份认证问题,每个微服务需要独立身份认证
- 难以重构,随着项目的迭代,可能需要重新划分微服务
- 某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定的困难
因此,我们需要网关介于客户端与服务器之间的中间层,所有外部请求率先经过微服务网关,客户端只需要与网关交互,只需要知道网关地址即可。这样便简化了开发且有以下优点:
- 易于监控,可在微服务网关收集监控数据并将其推送到外部系统进行分析
- 易于认证,可在微服务网关上进行认证,然后再将请求转发到后端的微服务,从而无需在每个微服务中进行认证
- 减少了客户端与各个微服务之间的交互次数
4|0网关解决了什么问题
网关具有身份认证与安全、审查与监控、动态路由、负载均衡、缓存、请求分片与管理、静态响应处理等功能。当然最主要的职责还是与“外界联系”。
总结一下,网关应当具备以下功能:
- 性能:API 高可用,负载均衡,容错机制。
- 安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
- 日志:日志记录,一旦涉及分布式,全链路跟踪必不可少。
- 缓存:数据缓存。
- 监控:记录请求响应数据,API 耗时分析,性能监控。
- 限流:流量控制,错峰流控,可以定义多种限流规则。
- 灰度:线上灰度部署,可以减小风险。
- 路由:动态路由规则。
5|0常用网关解决方案
5|1Nginx + Lua
Nginx 是由 IgorSysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,一个高性能的 HTTP 和反向代理服务器。Ngnix 一方面可以做反向代理,另外一方面做可以做静态资源服务器。
- Nginx 是 C 语言开发,而 Zuul 是 Java 语言开发
- Nginx 负载均衡实现,采用服务器实现负载均衡,而 Zuul 负载均衡的实现是采用 Ribbon + Eureka 来实现本地负载均衡
- Nginx 适合于服务器端负载均衡,Zuul 适合微服务中实现网关
- Nginx 相比 Zuul 功能会更加强大,因为 Nginx 可以整合一些脚本语言(Nginx + Lua)
- Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP / POP3 /SMIP 服务器。Zuul 是 Spring Cloud Netflix 中的开源的一个 API Gateway 服务器,本质上是一个 Servlet 应用,提供动态路由,监控,弹性,安全等边缘服务的框架。 Zuul 相当于是从设备和网站到应用程序后端的所有请求的前门。
- Nginx 适合做门户网关,是作为整个全局的网关,对外的处于最外层的那种;而 Zuul 属于业务网关,主要用来对应不同的客户端提供服务,用于聚合业务。各个微服务独立部署,职责单一,对外提供服务的时候需要有一个东西把业务聚合起来。
- Zuul 可以实现熔断、重试等功能,这是 Nginx 不具备的。
5|2Kong
Kong 是 Mashape 提供的一款 API 管理软件,它本身是基于 Ngnix + Lua 的,但比 Nginx 提供了更简单的配置方式,数据采用了 ApacheCassandra/PostgreSQL 存储,并且提供了一些优秀的插件,比如验证,日志,调用频次限制等。Kong 非常诱人的地方就是提供了大量的插件来扩展应用,通过设置不同的插件可以为服务提供各种增强的功能。
优点:基于 Nginx 所以在性能和稳定性上都没有问题。Kong 作为一款商业软件,在 Nginx 上做了很扩展工作,而且还有很多付费的商业插件。Kong 本身也有付费的企业版,其中包括技术支持、使用培训服务以及 API 分析插件。
缺点:如果你使用 Spring Cloud,Kong 如何结合目前已有的服务治理体系?
5|3Traefik
Traefik 是一个开源的 GO 语言开发的为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。 它支持多种后台 (Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API, file…) 来自动化、动态的应用它的配置文件设置。Traefik 拥有一个基于 AngularJS 编写的简单网站界面,支持 Rest API,配置文件热更新,无需重启进程。高可用集群模式等。
相对 Spring Cloud 和 Kubernetes 而言,目前比较适合 Kubernetes。
5|4Spring Cloud Netflix Zuul
Zuul 是 Netflix 公司开源的一个 API 网关组件,Spring Cloud 对其进行二次基于 Spring Boot 的注解式封装做到开箱即用。目前来说,结合 Sring Cloud 提供的服务治理体系,可以做到请求转发,根据配置或者默认的路由规则进行路由和 Load Balance,无缝集成 Hystrix。
虽然可以通过自定义 Filter 实现我们想要的功能,但是由于 Zuul 本身的设计是基于
单线程的接收请求和转发处理
,是阻塞 IO,不支持长连接。目前来看 Zuul 就显得很鸡肋,随着 Zuul 2.x 一直跳票(2019 年 5 月发布了 Zuul 2.0 版本),Spring Cloud 推出自己的 Spring Cloud Gateway。大意就是:Zuul 已死,Spring Cloud Gateway 永生(手动狗头)。
Zuul 1.0
Zuul 2.0
5|5Spring Cloud Gateway
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且还基于 Filter 链的方式提供了网关基本的功能。目前最新版 Spring Cloud 中引用的还是 Zuul 1.x 版本,而这个版本是基于过滤器的,是阻塞 IO,不支持长连接。
Zuul 2.x 版本一直跳票,2019 年 5 月,Netflix 终于开源了支持异步调用模式的 Zuul 2.0 版本,真可谓千呼万唤始出来。但是 Spring Cloud 已经不再集成 Zuul 2.x 了。
Spring Cloud Gateway 是基于 Spring 生态系统之上构建的 API 网关,包括:Spring 5,Spring Boot 2 和 Project Reactor。Spring Cloud Gateway 旨在提供一种简单而有效的方法来路由到 API,并为它们提供跨领域的关注点,例如:安全性,监视/指标,限流等。由于 Spring 5.0 支持 Netty,Http2,而 Spring Boot 2.0 支持 Spring 5.0,因此 Spring Cloud Gateway 支持 Netty 和 Http2 顺理成章。
5|6总结
API 网关在微服务架构中的作用大概是这样的:
我们目前所学习的网关关注的就是 Aggr API Gateway 这部分,在这里做聚合服务的操作。
6|0环境准备
zuul-demo
聚合工程。SpringBoot 2.2.4.RELEASE
、Spring Cloud Hoxton.SR1
。
eureka-server
:注册中心eureka-server02
:注册中心product-service
:商品服务,提供了根据主键查询商品接口http://localhost:7070/product/{id}
order-service
:订单服务,提供了根据主键查询订单接口http://localhost:9090/order/{id}
且订单服务调用商品服务。
7|0Nginx 实现 API 网关
点击链接观看:Nginx 实现 API 网关视频(获取更多请关注公众号「哈喽沃德先生」)
之前的课程中我们已经详细的讲解过 Nginx 关于反向代理、负载均衡等功能的使用,这里不再赘述。这里主要通过 Nginx 来实现 API 网关方便大家更好的学习和理解 Zuul 的使用。
7|1下载
官网:http://nginx.org/en/download.html 下载稳定版。为了方便学习,请下载 Windows 版本。
7|2安装
解压文件后直接运行根路径下的 nginx.exe
文件即可。
Nginx 默认端口为 80,访问:http://localhost:80/ 看到下图说明安装成功。
7|3配置路由规则
进入 Nginx 的 conf
目录,打开 nginx.conf
文件,配置路由规则:
7|4访问
之前我们如果要访问服务,必须由客户端指定具体服务地址访问,现在统一访问 Nginx,由 Nginx 实现网关功能将请求路由至具体的服务。
访问:http://localhost/api-product/product/1 结果如下:
访问:http://localhost/api-order/order/1 结果如下:
8|0Zuul 实现 API 网关
点击链接观看:Zuul 实现 API 网关视频(获取更多请关注公众号「哈喽沃德先生」)
8|1搭建网关服务
创建项目
创建 zuul-server
项目。
添加依赖
添加 spring cloud netflix zuul 依赖。
配置文件
application.yml
启动类
启动类需要开启 @EnableZuulProxy
注解。
8|2配置路由规则
URL 地址路由
通配符含义:
通配符 | 含义 | 举例 | 解释 |
---|---|---|---|
? | 匹配任意单个字符 | /product-service/? | /product-service/a,/product-service/b,... |
* | 匹配任意数量字符不包括子路径 | /product-service/* | /product-service/aa,/product-service/bbb,... |
** | 匹配任意数量字符包括所有下级路径 | /product-service/** | /product-service/aa,/product-service/aaa/b/ccc |
访问:http://localhost:9000/product-service/product/1 结果如下:
服务名称路由
微服务一般是由几十、上百个服务组成,对于 URL 地址路由的方式,如果对每个服务实例手动指定一个唯一访问地址,这样做显然是不合理的。
Zuul 支持与 Eureka 整合开发,根据 serviceId 自动从注册中心获取服务地址并转发请求,这样做的好处不仅可以通过单个端点来访问应用的所有服务,而且在添加或移除服务实例时不用修改 Zuul 的路由配置。
添加 Eureka Client 依赖
配置注册中心和路由规则
启动类
访问
访问:http://localhost:9000/product-service/product/1 结果如下:
简化路由配置
Zuul 为了方便大家使用,提供了默认路由配置:路由 id 和 微服务名称
一致,path 默认对应 /微服务名称/**
,所以以下配置就没必要再写了。
访问
此时我们并没有配置任何订单服务的路由规则,访问:http://localhost:9000/order-service/order/1 结果如下:
8|3路由排除
我们可以通过路由排除设置不允许被访问的资源。允许被访问的资源可以通过路由规则进行设置。
URL 地址排除
服务名称排除
8|4路由前缀
访问
访问:http://localhost:9000/api/product-service/product/1 结果如下:
下一篇我们讲解 Zuul 网关过滤器实现统一鉴权以及网关过滤器异常统一处理,记得关注噢~