
Zuul 简介
Spring Cloud Zuul 是Spring Cloud Netflix 子项目的核心组件之一,可以作为微服务架构中的API网关使用,支持动态路由与过滤功能,本文将对其用法进行详细介绍。
API 网关为微服务架构中的服务提供了统一的访问入口,客户端通过 API 网关访问相关服务。API 网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。
创建项目模块
这里我们创建一个 zuul-proxy 模块来演示 zuul 的常用功能。
引入依赖
在 pom.xml 中添加相关依赖
1 | <dependency> |
相关配置
在 application.yml 中进行配置
1 | server: |
在启动类上添加 @EnableZuulProxy 注解来启用 Zuul 的 API 网关功能
1 |
|
常用功能
启动相关服务
这里我们通过启动 eureka-server,两个 user-service,feign-service 和 zuul-proxy 来演示 Zuul 的常用功能。
配置路由规则
我们可以通过修改application.yml中的配置来配置路由规则,这里我们将匹配/userService/**
的请求路由到user-service服务上去,匹配/feignService/**
的请求路由到feign-service上去。
1 | zuul: |
访问 http://localhost:8801/userService/user/1 可以发现请求路由到了 user-service 上
访问 http://localhost:8801/feignService/user/1 可以发现请求路由到了 feign-service 上
默认路由规则
Zuul 和 Eureka 结合使用,可以实现路由的自动配置,自动配置的路由以服务名称为匹配路径,相当于如下配置:
1 | zuul: |
- 访问 http://localhost:8801/user-service/user/1 同样可以路由到了 user-service 上
- 访问 http://localhost:8801/feign-service/user/1 同样可以路由到了 feign-service 上
如果不想使用默认的路由规则,可以添加以下配置来忽略默认路由配置:
1 | zuul: |
负载均衡功能
多次调用 http://localhost:8801/user-service/user/1 进行测试,可以发现运行在 8201 和 8202 的 user-service 服务交替打印信息。
配置访问前缀
我们可以通过以下配置来给网关路径添加前缀,此处添加了 /proxy 前缀,这样我们需要访问 http://localhost:8801/proxy/user-service/user/1 才能访问到 user-service 中的接口。
1 | zuul: |
Header过滤及重定向添加Host
Zuul 在请求路由时,默认会过滤掉一些敏感的头信息,以下配置可以防止路由时的 Cookie 及 Authorization 的丢失:
1 | zuul: |
Zuul 在请求路由时,不会设置最初的 host 头信息,以下配置可以解决:
1 | zuul: |
查看路由信息
我们可以通过 Spring Boot Actuator 来查看 Zuul 中的路由信息。
在 pom.xml 中添加相关依赖:
1 | <dependency> |
修改 application.yaml 配置文件,开启查看路由的端点:
1 | management: |
通过访问 http://localhost:8801/actuator/routes 查看简单路由信息:
通过访问 http://localhost:8801/actuator/routes/details 查看详细路由信息:
过滤器
路由与过滤是 Zuul 的两大核心功能,路由功能负责将外部请求转发到具体的服务实例上去,是实现统一访问入口的基础,过滤功能负责对请求过程进行额外的处理,是请求校验过滤及服务聚合的基础。
过滤器类型
Zuul 中有以下几种典型的过滤器类型。
- pre:在请求被路由到目标服务前执行,比如权限校验、打印日志等功能;
- routing:在请求被路由到目标服务时执行,这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方;
- post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能;
- error:请求在其他阶段发生错误时执行。
过滤器的生命周期
下图描述了一个 HTTP 请求到达 API 网关后,如何在各种不同类型的过滤器中流转的过程:
自定义过滤器
接下来我们自定义一个过滤器来演示下过滤器的作用。
添加 PreLogFilter 类继承 ZuulFilter
这是一个前置过滤器,用于在请求路由到目标服务前打印请求日志。
1 |
|
过滤器功能演示
添加过滤器后,我们访问 http://localhost:8801/user-service/user/1 测试下,会打印如下日志。
1 | 2019-10-05 15:13:10.232 INFO 11040 --- [nio-8801-exec-7] com.antonio.cloud.filter.PreLogFilter : Remote host:0:0:0:0:0:0:0:1,method:GET,uri:/user-service/user/1 |
核心过滤器
过滤器名称 | 过滤类型 | 优先级 | 过滤器的作用 |
---|---|---|---|
ServletDetectionFilter | pre | -3 | 检测当前请求是通过DispatcherServlet处理运行的还是ZuulServlet运行处理的。 |
Servlet30WrapperFilter | pre | -2 | 对原始的HttpServletRequest进行包装。 |
FormBodyWrapperFilter | pre | -1 | 将Content-Type为application/x-www-form-urlencoded或multipart/form-data的请求包装成FormBodyRequestWrapper对象。 |
DebugFilter | route | 1 | 根据zuul.debug.request的配置来决定是否打印debug日志。 |
PreDecorationFilter | route | 5 | 对当前请求进行预处理以便执行后续操作。 |
RibbonRoutingFilter | route | 10 | 通过Ribbon和Hystrix来向服务实例发起请求,并将请求结果进行返回。 |
SimpleHostRoutingFilter | route | 100 | 只对请求上下文中有routeHost参数的进行处理,直接使用HttpClient向routeHost对应的物理地址进行转发。 |
SendForwardFilter | route | 500 | 只对请求上下文中有forward.to参数的进行处理,进行本地跳转。 |
SendErrorFilter | post | 0 | 当其他过滤器内部发生异常时的会由它来进行处理,产生错误响应。 |
SendResponseFilter | post | 1000 | 利用请求上下文的响应信息来组织请求成功的响应内容。 |
禁用过滤器
我们可以对过滤器进行禁用的配置,配置格式如下:
1 | zuul: |
以下是禁用 PreLogFilter 的示例配置:
1 | zuul: |
Ribbon 和 Hystrix 的支持
由于 Zuul 自动集成了 Ribbon 和 Hystrix,所以 Zuul 天生就有负载均衡和服务容错能力,我们可以通过 Ribbon 和 Hystrix 的配置来配置 Zuul 中的相应功能。
可以使用 Hystrix 的配置来设置路由转发时 HystrixCommand 的执行超时时间:
1 | hystrix: |
可以使用 Ribbon 的配置来设置路由转发时请求连接及处理的超时时间:
1 | ribbon: #全局配置 |
常用配置
1 | zuul: |
更多请移步:https://antoniopeng.com
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !