一、概述
1、什么是路由
Zuul 是 Netflix OSS 中的一员,是一个基于 JVM 路由和服务端的负载均衡器。提供路由、监控、弹性、安全等方面的服务框架。Zuul 能够与 Eureka、Ribbon、Hystrix 等组件配合使用。
2、官方解释
Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.
Zuul作为微服务系统的网关组件,是从设备和网站到Netflix流应用程序后端的所有请求的前门。作为边缘服务应用程序,Zuul旨在实现动态路由,监控,弹性和安全性。
3、不用zuul,客户端直接与各个微服务通讯存在的问题
- 客户端会多次请求不同的微服务,增加了客户端的复杂性。
- 存在跨域请求,在一定场景下处理相对复杂。
- 认证复杂,每个服务都需要独立认证。
- 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能会将多个微服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通讯,那么重构就会很难实施。
- 某些微服务可能使用了防火墙/浏览器不友好的协议,直接访问会有一定困难。
4、zuul的功能
Zuul包含了对请求的路由和过滤两个最主要的功能:
路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。
滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。
注:Zuul服务最终还是会注册进Eureka
5、作用
- 易于监控,可在微服务网关收集监控数据并将其推送到外部系统进行分析。使用网关时客户端至只与网关交互,降低客户端的调用逻辑的复杂度,同时网关也可以实现认证逻辑简化内部服务之间相互调用的复杂度。
- 对不同客户端的支持及数据的聚合,如一个网站有web端,手机端,页面所需的数据有同有异,可以将数据整合或者裁剪,减少客户端的请求次数,比如BFF架构。
- 可以更好的对项目微服务封装,可将项目的微服务统一封装在一个内网环境中,减少了客户端与各个微服务之间的交互次数。只通过网关提供服务,同时网关也可以对安全,认证,监控,防御单独强化。
- 易如认证,可在微服务网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
6、架构图
zuul
是一个网关和负载均衡器,在通过 ribbon
或者 feign
实现了客户端负载均衡之后,zuul
在服务端实现负载均衡。zuul
支持用任何 JVM
语言来编写规则和过滤条件。
服务网关是微服务架构中不可或缺的部分。通过服务网关统一向外系统提供 REST API
的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。
Spring Cloud Netflix
中的 Zuul
就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
说明:
首先一个 Http 请求进来之后,一定会经过 Zuul 的 Servlet,也可能会经过 Zuul Filter Runner。Runner 是统管所有 Filter 链的顺序或者数据的交互,Filter Runner主要是管理整个 Zuul 的生命周期。
用户请求进来后会有很多信息,通过 Request Context 的上下文在Zuul的生命周期中进行传递。FilterLoader 是当 Zuul 启动的时候会从本地或从动态 Filter 里的指定目录将 Filter 进行装载。
二、路由基本配置
1、新建一个Module模块microservicecloud-zuul-gateway-9527
2、修改POM文件
<dependencies>
<!-- zuul路由网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- actuator监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- hystrix容错-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!-- 自己定义的api -->
<dependency>
<groupId>com.itan</groupId>
<artifactId>microservicecloud-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 热部署插件 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
3、修改YAML文件
server:
port: 9527
spring:
application:
# 微服务的名称
name: microservicecloud-zuul-gateway
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7004.com:7004/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: gateway-9527.com #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址
# info页面说明信息
info:
app.name: itan-microservicecloud
company.name: www.itan.com
build.artifactId: $project.artifactId$
build.version: $project.version$
4、修改hosts文件
127.0.0.1 myzuul.com
5、主启动类上加 @EnableZuulProxy
注解
@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_ZuulApp {
public static void main(String[] args) {
SpringApplication.run(Zuul_9527_ZuulApp.class,args);
}
}
6、启动
启动3个eureka集群
启动一个服务提供类
启动路由
7、测试
不用路由:
http://localhost:8001/dept/get/2
启用路由:
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
三、路由访问映射规则
1、zuul的配置及说明
zuul:
# 统一访问前缀
prefix: /itan
# 原真实服务名,单个具体,多个用"*"
# ignored-services: "*"
ignored-services: microservicecloud-dept
# 路径列表,包含多个路由名,路由名可以任意命名
routes:
# 路由需要的服务名
mydept.serviceId: microservicecloud-dept
# 路由需要的访问路径
mydept.path: /mydept/**
2、全配置
server:
port: 9527
spring:
application:
# 微服务的名称
name: microservicecloud-zuul-gateway
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7004.com:7004/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: gateway-9527.com #自定义服务名称信息
prefer-ip-address: true #访问路径可以显示IP地址
# info页面说明信息
info:
app.name: itan-microservicecloud
company.name: www.itan.com
build.artifactId: $project.artifactId$
build.version: $project.version$
zuul:
# 统一访问前缀
prefix: /itan
# 原真实服务名,单个具体,多个用"*"
# ignored-services: "*"
ignored-services: microservicecloud-dept
# 路径列表,包含多个路由名,路由名可以任意命名
routes:
# 路由需要的服务名
mydept.serviceId: microservicecloud-dept
# 路由需要的访问路径
mydept.path: /mydept/**
3、测试
路由地址:
http://myzuul.com:9527/microservicecloud-dept/dept/get/2
(没有配置访问前缀和真是服务名)路由地址:
http://myzuul.com:9527/mydept/dept/get/2
(没有配置访问前缀)路由地址:
http://myzuul.com:9527/itan/mydept/dept/get/2
(配置了访问前缀)
四、过滤器是Zuul的核心组件
1、概述
Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
2、四种过滤器类型
PRE
:这种过滤器在请求被路由之前调用。我们可以利用这种过滤器实现身份验证、在集群中选择请求的服务、记录调试信息等。ROUTING
:这种过滤器将请求路由到微服务,在路由请求时候被调用。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient
或Netfilx Ribbon
请求微服务。POST
:这种过滤器在路由到微服务之后执行。这种过滤器可用来为响应添加标准的Http Header
、收集统计信息和指标、将响应从微服务发送给客户端等。ERROR
:在其他阶段发生错误时执行该过滤器。
3、zuul中默认实现的filter
类型 | 服务 | 过滤器 | 功能 |
---|---|---|---|
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
route | 1 | DebugFilter | 标记调试标志 |
route | 5 | PreDecorationFilter | 处理请求上下文供后续使用 |
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
数字越大,优先级越低。
路由功能在真正运行时,它的路由映射和请求转发都是由几个不同的过滤器完成的。其中,路由映射主要通过pre
类型的过滤器完成,它将请求路径与配置的路由规则进行匹配,以找到需要转发的目标地址;而请求转发的部分则是由route
类型的过滤器来完成,对pre
类型过滤器获得的路由地址进行转发。所以说,过滤器可以说是zuul
实现api
网关功能最核心的部件,每一个进入zuul
的http
请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。
五、总结
Zuul包含了对请求的路由和过滤两个功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础;而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。