zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用。
Zuul是Netflix开源的微服务网关,他可以和Eureka、Ribbon、Hystrix等组件配合使用,它的核心是一些列的过滤器,这些过滤器可以实现的功能:身份认证与安全、审查与监控、动态路由、压力测试、负载分配、静态响应处理、多区域弹性。
Zuul 作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在以下 6 个方面。
1、Zuul、Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能,Zuul 能够 将请求流量按某种策略分发到集群状态的多个服务实例。
2、网关将所有服务的 API 接口统一聚合,并统一对外暴露。外界系统调用 API 接口时, 都是由网关对外暴露的 API 接口,外界系统不需要知道微服务系统中各服务相互调 用的复杂性。微服务系统也保护了其内部微服务单元的 API 接口,防止其被外界直 接调用,导致服务的敏感信息对外暴露。
3、网关服务可以做用户身份认证和权限认证,防止非法请求操作 API 接口,对服务器 起到保护作用。
4、 网关可以实现监控功能,实时日志输出,对请求进行记录。
5、 网关可以用来实现流量监控,在高流量的情况下,对服务进行降级。
6、API 接口从内部服务分离出来,方便做测试。
Zuul可以通过加载动态过滤机制,从而实现以下各项功能:
验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。动态路由: 以动态方式根据需要将请求路由至不同后端集群处。压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。相同点
Zuul和Nginx都可以实现负载均衡、反向代理(隐藏真实ip地址),过滤请求,实现网关的效果
不同点
Nginx–c语言开发 Zuul–java语言开发 Zuul负载均衡实现:采用ribbon+eureka实现本地负载均衡 Nginx负载均衡实现:采用服务器实现负载均衡 Nginx相比zuul功能会更加强大,因为Nginx整合一些脚本语言(Nginx+lua) Nginx适合于服务器端负载均衡 Zuul适合微服务中实现网关
Zuul 的核心是一系列过滤器,可以在 Http 请求的发起和响应返回期间执行一系列的过滤器。
Zuul 包括以下 4 种过滤器
PRE 过滤器:它是在请求路由到具体的服务之前执行的,这种类型的过滤器可以做 安全验证,例如身份验证、参数验证等。ROUTING 过滤器:它用于将请求路由到具体的微服务实例。在默认情况下,它使用 Http Client 进行网络请求。POST 过滤器:它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计 信息、指标,以及将响应传输到客户端。ERROR 过滤器:它是在其他过滤器发生错误时执行的。Zuul 采取了动态读取、编译和运行这些过滤器。过滤器之间不能直接相互通信,而是通 过 RequestContext 对象来共享数据,每个请求都会创建一个 RequestContext 对象。
Zuul 过滤器具有以下关键特性
Type(类型):Zuul 过滤器的类型,这个类型决定了过滤器在请求的哪个阶段起作用, 例如 Pre、Post 阶段等。Execution Order(执行顺序):规定了过滤器的执行顺序,Order 的值越小,越先执行。Criteria(标准):Filter 执行所需的条件。Action(行动):如果符合执行条件,则执行 Action(即逻辑代码)。Zuul 请求的生命周期
正常流程:
请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
异常流程:
整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回。
如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的时,请求不会再到达POST过滤器了。
1、url方式(不建议使用)
zuul: routes: api-a: #key随意定义 path: /service/a/** #匹配service/a/为前缀的所有路径 url: http://127.0.0.1:8082 #匹配service/a/为前缀的所有路径转发到此地址请求http://127.0.0.1:8769/service/a/1 路由成功
url方式,路径对应的服务地址写死的,不适用与同一个服务有多个实例的情况
2、面向服务的路由
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ server: port: 8769 spring: application: name: service-zuul zuul: routes: api-a: path: /service/a/** serviceId: service-ribbon1 api-b: path: /service/b/** serviceId: service-ribbon2请求http://127.0.0.1:8769/service/a/1 路由成功
Zuul作为网关的其中一个重要功能,就是实现请求的鉴权.而这个动作我们往往是通过Zuul提供的过滤器来实现的.
Zuul中的顶级过滤器是ZuulFilter.其中定义了四个最重要的方法.
public abstract ZuulFilter implements IZuulFilter{ abstract public String filterType(); //过滤器类型 abstract public int filterOrder(); //过滤器顺序.这个值越大,优先级越低 boolean shouldFilter(); //来自IZuulFilter.要不要过滤 Object run() throws ZuulException; //IZuulFilter. 过滤逻辑 } shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。run:过滤器的具体业务逻辑。filterType:返回字符串,代表过滤器的类型。包含以下4种: pre:请求在被路由之前执行routing:在路由请求时调用post:在routing和errror过滤器之后调用error:处理请求时发生错误调用 filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。Zuul自定义过滤器
Spring Cloud(十二)Zuul实战
Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制。
但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议我们手动进行配置:
zuul: retryable: true ribbon: ConnectTimeout: 500 # 连接超时时间(ms) ReadTimeout: 2000 # 通信超时时间(ms),超时时长不能超过hystrix的熔断时长 OkToRetryOnAllOperations: true # 是否对所有操作重试 MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数 MaxAutoRetries: 1 # 同一实例的重试次数 hystrix: command: default: execution: isolation: thread: timeoutInMillisecond: 6000 # 熔断超时时长:6000msPS
ConnectTimeout(连接超时时长) + ReadTimeout(读取超时时长) 是2500。
但是ribbon会进行一次重试. 那么默认就是(ConnectTimeout+ReadTimeout) * 2 是真正的总超时时长。
所以timeoutInMillisecond熔断的时长必须要超过这个时间,否则会报错.。或者把ribbon的MaxAutoRetries设为0,那么久不进行重试了。
Zuul作为服务网关,控制这全部请求的统一入口。Zuul的高可用服务提供是必要的。
Nginx+Zuul集群实现高可用网关
1、通过Nginx实现负载均衡 2、Zuul集群实现高可用