Zuul 简介

Zuul是什么

  • ZuulNetflix开源的一个API Gateway 服务器, 本质上是一个Web servlet应用,他可以和Eureka,Ribbon,Hystrix等组件配合使用。

  • Zuul组件的核心是一系列的过滤器filters,其作用可以类比Servlet框架的Filter,或者AOP

为什么要用Zuul

  • 在分布式架构中,对外提供的服务,在无网关的情况下,API接口直接暴露给服务调用方,当调用方增多,不同业务调用方各不相同,势必需要添加定制化访问权限、校验等逻辑。当添加API网关后,再第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制,后将请求均衡分发给后台服务端。Zuul就是提供负载均衡、反向代理、权限认证的这么一个API gateway
  • 微服务网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关
logo
logo

Zuul 提供什么功能

  • Zuul组件的核心是一系列的过滤器,这些过滤器可以完成以下功能:

    • 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求
    • 审查与监控:
    • 动态路由:动态将请求路由到不同后端集群
    • 压力测试:逐渐增加指向集群的流量,以了解性能
    • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
    • 静态响应处理:边缘位置进行响应,避免转发到内部集群
    • 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB(ElasticLoad Balancing)使用多样化
  • Spring CloudZuul进行了整合和增强。目前Zuul使用的默认是ApacheHTTP Client,也可以使用Rest Client,可以设置ribbon.restclient.enabled=true.

简单示例

添加Maven依赖配置

1
2
3
4
5
6
7
8
<dependencies>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

</dependencies>

添加配置文件application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
port: 9001
spring:
application:
name: zuul-gateway
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://localhost:9010/eureka/,http://localhost:9011/eureka/
zuul:
routes:
baidu-url: #传统路由方式
path: /baidu/**
url: http://www.baidu.com/
provider: #面向服务的路由
path: /provider/**
serviceId: eureka-provider
consumer: #面向服务的路由
path: /consumer/**
serviceId: eureka-consumer

启动类加上@EnableZuulProxy注解

1
2
3
4
5
6
7
8
@EnableZuulProxy
@SpringBootApplication
public class ZuulApplication {

public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}

添加一个过滤器 AccessFilter.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class AccessFilter extends ZuulFilter{

private Logger logger = LoggerFactory.getLogger(this.getClass());

/**
* 定义过滤器的类型,决定过滤器在请求的那个生命周期中执行
* pre 请求被路由之前
* routing 在路由请求时被调用
* post 在routing和error过滤器之后被调用
* error 处理请求时发生错误时被调用
* @return
*/
@Override
public String filterType() {
// 代表会在请求被路由之前被执行
return "pre";
}

/**
* 定义过滤器的顺序,当请求在一个阶段中存在多个过滤器时,可以根据该值来决定执行顺序
* @return
*/
@Override
public int filterOrder() {
return 0;
}

/**
* 判断过滤器是否需要被执行
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}

/**
* 过滤器的具体实现
* @return
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
logger.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());
Object accessToken = request.getParameter("accessToken");
if (accessToken == null) {
logger.error("access check failed");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
logger.error("access check passs");
return null;
}
}

解析

zuul默认支持hystrix和ribbon

1
2
3
4
5
6
7
8
9
10
11
12
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 60000 // 设置API网关中路由转发请求的HystrixCommand执行超时时间,就是整个路由转发请求的执行时间
ribbon:
ConnectTimeout: 60000 // 设置创建请求连接的超时时间,如果该值小于上面的HystrixCommand执行超时时间,会自动进行重试路由请求
ReadTimeout: 60000 // 设置请求连接建立之后执行处理的超时时间,如果该值小于上面的HystrixCommand执行超时时间,会自动进行重试路由请求
  • Zuul的过滤器之间没有直接的相互通信,他们之间通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。

  • Zuul的过滤器是由Groovy写成,这些过滤器文件被放在Zuul Server上的特定目录下面,Zuul会定期轮询这些目录,修改过的过滤器会动态的加载到Zuul Server中以便过滤请求使用。

过滤器机制

  • Zuul大部分功能都是通过过滤器来实现的。Zuul中定义了四种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期,下面有几种标准的过滤器类型:
    • (1) PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
    • (2) ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClientNetfilx Ribbon请求微服务。
    • (3) POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
    • (4) ERROR:在其他阶段发生错误时执行该过滤器。
过滤器的生命周期
  • 各种不同类型的过滤器流转流程
    • 当客户端请求过来首先会到 pre filters 这样的一个前置过滤器做一些处理,然后调用自定义的过滤器
    • 前置过滤器执行完了之后会调用 routing filters 过滤器 ,看名字都知道这是做路由分发的过滤器
    • 在路由的过程中出现了异常,那么会走 error filters过滤器,然后再走 post filters 过滤器 ,或者正常路由完成也会走到post filters
    • post filters过滤器负责处理响应 ,最后把结果响应给客户端

内置的特殊过滤器
  • 下面是zuul默认实现的过滤器

其他

  • 当我们为Spring Cloud Zuul构建的API网关服务引入Spring Cloud Eureka之后,它会为Eureka中的每个服务都自动创建一个默认路由规则,这些默认规则的path会使用ServiceId配置的服务名作为请求前缀

  • Spring Cloud Zuul还特别提供了/routes端点来返回当前的所有路由规则

总结

参考