四、网关:spring-cloud-Zuul

导读:本篇文章讲解 四、网关:spring-cloud-Zuul,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1 介绍

1.1 前言

​ 在微服务框架中,每个对外服务都是独立部署的,对外的Api或者服务地址都不是不尽相同的。对于内部而言,通过注册中心自动感知即可。但大部分情况下,服务都是提供给外部系统进行调用的,不可能同享一个注册中心。同时一般上内部的微服务都是在内网的,和外界是不连通的。而且,就算每个微服务对外开放,对于调用者而言,调用不同的服务的地址或者参数也是不尽相同的,这样就会造成消费者客户端的复杂性,同时,可能微服务可能是不同的技术栈实现的,有的是Http、Rpc或者Websocket等等,也会进一步加大客户端的调用难度。所以,一般上都有会有个Api网关,根据请求的url不同,路由到不同的服务上去,同时入口统一了,还能进行统一的身份鉴权、日志记录、分流等操作。

1.2 什么是Zuul网关

​ 微服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。Zuul 是Zuul是Netflix开源的微服务网关,本质上是一个Web Servlet应用,可以和Eureka、Ribbon、Hystrix等组件配合使用,Spring Cloud对Zuul进行了整合与增强,和其他组件配合使用相对方便,Zuul的主要功能是路由转发和过滤器。

​ Zuul基于JVM的路由器和服务器端负载均衡器。同时,Zuul的规则引擎允许规则和过滤器基本上用任何JVM语言编写,内置支持Java和Groovy。这个功能,就可以实现动态路由的功能了。当需要添加某个新的对外服务时,一般上不停机更新是通过数据缓存配置或者使用Groovy进行动态路由的添加的。

1.3网关的意义

​ 微服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。

​ 在未加入网关时,一般上会在服务外网架设一个负载均衡,如Nginx等。此时,微服务的组成如下图所示:

加入网关前

​ 此时,对于Open Service而言可能需要提供权限控制等和业务无关的能力,这样本身就破坏了微服务服务单一的原则。所以,一般上在Open Service之上,还有一层服务提供诸如通用的权限校验、参数校验等功能,此服务就是网关了。之后,对于内部微服务而言,只需要关系各自微服务提供的业务功能即可,无需去关心其他非业务相关的功能。

Zuul做为路由网关,在微服务架构中有着十分重要的作用,体现在这几方面:

​ a. Zuul、Ribbon、Eureka结合,可以实现智能路由和负载均衡的功能,Zuul能够将请求流量按照某种策略分发到集群状态的多个服务实例;

​ b. 网关将所有服务的Api接口统一聚合,并统一对外暴露,外界系统调用Api接口时,都是由网关对外暴露的Api接口,外界系统不需要知道微服务系统中各服务相互调用的复杂性,保护了其微服务单元Api接口防止被外界直接调用,导致服务的敏感信息对外暴露;

​ c. 网关服务可以做到用户身份认证和权限认证,防止非法请求操作Api接口,对服务器起保护作用;

​ d. 网关可以流量监控、实时日志记录等功能;

加入Zuul网关后

加入网关之后

Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

a.验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。

b.审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。

c.动态路由: 以动态方式根据需要将请求路由至不同后端集群处。

d.压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。

e.负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。

f.静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。

g.多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。

1.4 网关的优缺点

优点:

​ a.减少Api请求次数

​ b.限流

​ c.缓存

​ d.统一认证

​ e.降低微服务的复杂度

​ f.支持混合通信协议(前端只和api通信,其他的由网关调用)

缺点:

​ a.网关需高可用,可能产生单点故障

​ b.管理复杂

2 Zuul的三大模块

​ 目前网上大多数关于Zuul的相关讨论大都是 Spring-Cloud-Zuul相关的,但是笔者认为Spring Cloud Zuul 有利也有弊。好处就是开发起来比较方便,一个注解就可以启用一个网关,并且增加了一些默认的过滤器组件;但是Spring Cloud 为了开发者的快速接入,也对Netflix Zuul 的一些功能做了阉割。Netflix Zuul 主要包含了三大模块:Zuul核心模块、过滤器加载模块、过滤器管理模块。其中核心模块和过滤器加载模块,在Spring Cloud Zuul 的定制版本中,都没有做太大的改动。

zuul

2.1 核心模块

​ 请求接收然后通过 pre、route、post 三个主要类型的过滤器。当然了,还有另外2 中上图中没有展现,就是 error 和 custom 类型的过滤器。error 是处理异常时的处理动作,custom 是自定义处理请求的过滤流程。上面各个过滤器之间是通过 RequestContext (Map类型,ThreadLocal 变量) 来做上下文传递的。ZuulFilterRunner 组织了各种类型的过滤器的执行逻辑。

2.2.1 ZuulServlet

ZuulServlet 依次执行了 pre过滤器、route过滤器、post过滤器;当产生错误时,会执行error 过滤器。以上各种类型的 Filter 会委派给ZuulRunner 去执行。

2.2.2 ZuulRunner

ZuulRunner 本身也没什么逻辑,而是使用了单例的处理器 FilterProcessor 来处理。

2.2.3FilterProcessor

FilterProcessor 回去从 FilterLoader 中获取各个类型的过滤器,并且顺序执行。

2.2.4 RequestContext

各个 Filter 执行的过程中不能直接相互通信,参数的传递依赖是通过 线程本地变量 RequestContext 来实现的。

2.2.4 ZuulFilter

Zuul提供了动态读取、编译和执行Filter的框架。各个Filter间没有直接联系,但是都通过RequestContext共享一些状态数据。尽管Zuul支持任何基于JVM的语言,但是过滤器目前是用Groovy编写的。 每个过滤器的源代码被写入到Zuul服务器上的一组指定的目录中,这些目录将被定期轮询检查是否更新。Zuul会读取已更新的过滤器,动态编译到正在运行的服务器中,并后续请求中调用。

关键特性:

· Type:用以表示路由过程中的阶段(内置包含PRE、ROUTING、POST和ERROR)

· Execution Order:表示相同Type的Filter的执行顺序

· Criteria:执行条件

· Action:执行体

请求生命周期:

四、网关:spring-cloud-Zuul

Zuul 大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期。

· PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

· ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient 或 Netfilx Ribbon 请求微服务。

· POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

· ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul 还允许我们创建自定义的过滤器类型。例如,我们可以定制一种 STATIC 类型的过滤器,直接在 Zuul 中生成响应,而不将请求转发到后端的微服务。

Zuul 中默认实现的 Filter

类型 顺序 过滤器 功能
pre -3 ServletDetectionFilter 标记处理 Servlet 的类型
pre -2 Servlet30WrapperFilter 包装 HttpServletRequest 请求
pre -1 FormBodyWrapperFilter 包装请求体
pre 1 DebugFilter 标记调试标志
pre 5 PreDecorationFilter 处理请求上下文供后续使用
route 10 RibbonRoutingFilter serviceId 请求转发
route 100 SimpleHostRoutingFilter url 请求转发
route 500 SendForwardFilter forward 请求转发
post 0 SendErrorFilter 处理有错误的请求响应
post 1000 SendResponseFilter 处理正常的请求响应

2.2 过滤器加载模块

过滤器加载模块主要是给Core 模块的FilterRunner 提供服务的,也就是提供编译好的Filter组件。其中的FilterFileManager 是以轮询的方式,不断的从包含groovy 脚本的目录中加载文件,提供给 FilterLoader 编译和管理。

具体流程:

过滤器加载模块主要提供给 Core 模块,从磁盘(或者网络等其他介质)中加载Filter ,并完成实例化的过程,以备Core 模块的使用。其中FilterFileManager 负责从磁盘中加载数据,然后调用FilterLoader 的单例,去实例化Filter以备用。FilterFileManager会启用一个守护线程,在后台不断地循环管理Filter 文件(源码中每次循环后,会休息1秒钟)。循环每个Filter 都会调用 FilterLoader.getInstance().putFilter() 将其放入FilterLoader的Map中。

2.3 过滤器管理模块

过滤器管理模块对于运维和做一些功能增强时非常有帮助,大多数情况下都需要对其做定制开发,从而适应各个公司不同的业务需求。上面的过滤器加载模块最终交互的对象是磁盘文件,那么过滤器管理模块就相对是个独立的东西了。相关的操作就是Filter 文件。

具体流程:

过滤器管理模块直接操作文件的类是:ZuulFilterPoller 。它会起一个线程,不断的循环去抓取Filter的元数据(源码中由ZuulFilterDAO提供)。官方给的默认的实现是 Cassandra,也就是Filter的元数据是从 Cassandra 数据库中获取的。但是这个数据库在国内用的相对较少,如果要定制的话,通常会改成 MySQL 或者 Http接口的方式去实现。ZuulFilterPoller 中起了一个循环线程,不断的去获取元数据的信息,从而更新Filter。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71427.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!