SpringCloud之Zuul:微服务系统架构网关

目录

 

1. 什么是Zuul?

2. Zuul深入剖析

2.1 过滤器

2.2 源码理解

3. Zuul应用场景

3.1 Zuul如何实现路由转发?

3.2 Zuul如何实现限流熔断?

3.3 Zuul如何进行压力测试

4. Zuul2.0概述


1. 什么是Zuul?

Zuul是从设备、网站到应用程序后端的所有请求的前门。作为边缘服务应用程序,Zuul旨在实现动态路由,监控,弹性和安全性。

Zuul使用了各种不同类型的过滤器,这使我们能够快速灵活地将功能应用于边缘服务。这些过滤器帮助我们执行以下功能:

  • 安全认证-识别每个资源的身份验证要求,并拒绝不满足要求的请求。
  • 日志监控-跟踪某些数据和统计信息,以便为我们提供准确的生产视图。
  • 路由转发-根据需要将请求动态路由到不同的后端群集。
  • 压力测试-逐渐增加到群集的流量以评估性能。
  • 限流-为每种类型的请求分配容量,并丢弃超出限制的请求。
  • 熔断-直接在边缘构建一些响应,而不是将其转发到内部集群

Zuul 在 Netflix 的应用场景:

 

2. Zuul深入剖析

Zuul 是基于 Servlet 开发的,通过 Zuul 的核心构架图可以看出 Zuul 是由很多的过滤器组成的。

2.1 过滤器

Filter是Zuul的核心,用来实现对外服务的控制。Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”,整个生命周期可以用下图来表示。

 

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

  • PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  • ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
  • ERROR:在其他阶段发生错误时执行该过滤器。

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

2.2 源码理解

- Zuul 是如何将各个 Filter 的处理结果连接起来的?

答:通过 RequestContext 对象,使用 ThreadLocal。

关键源码:

public class RequestContext extends ConcurrentHashMap<String, Object> {
    protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() {
        @Override
        protected RequestContext initialValue() {
            try {
                return contextClass.newInstance();
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
    };

    public static RequestContext getCurrentContext() {
        if (testContext != null) return testContext;

        RequestContext context = threadLocal.get();
        return context;
    }

    public StringBuilder getFilterExecutionSummary() {
        if (get("executedFilters") == null) {
            putIfAbsent("executedFilters", new StringBuilder());
        }
        return (StringBuilder) get("executedFilters");
    }

    public void unset() {
        threadLocal.remove();
    }
}

 

3. Zuul应用场景

红绿部署、开发者测试分支、埋点测试、压力测试、调试路由、金丝雀测试、粘性金丝雀、失败注入测试、降级测试、跨区域高可用、防爬防攻击、健康检查和屏蔽坏节点。

 

以下是我在学习过程中的几个思考。

3.1 Zuul如何实现路由转发?

通过实现 Filter 来实现:

过滤器样例:

public class MyFilter extends ZuulFilter {
    @Override
    String filterType() {
        return "pre"; //定义filter的类型,有pre、route、post、error四种
    }

    @Override
    int filterOrder() {
        return 10; //定义filter的顺序,数字越小表示顺序越高,越先执行
    }

    @Override
    boolean shouldFilter() {
        return true; //表示是否需要执行该filter,true表示执行,false表示不执行
    }

    @Override
    Object run() {
        return null; //filter需要执行的具体操作
    }
}

3.2 Zuul如何实现限流熔断?

实现一个过滤器,run()方法为空。

3.3 Zuul如何进行压力测试

实现一个压力测试的过滤器,路由指定到某个服务。

 

4. Zuul2.0概述

Zuul 1.0是基于 Servlet 来实现的,是一种 BIO 网络通信模式。

 

这种模式优点是:模型简单、开发调试运维简单。

缺点是:线程上下文切换会有开销,并且存在连接数限制。

 

基于1.0版本,Zuul 推出了 2.0版本,在网络通信模型进行了优化(还有其他)。

采用 AIO 的模式,相比于1.0版本,在线程开销上减小了,也能够接入更多的连接数。

但是缺点是:编程模型变复杂的同时也提高了开发运复杂度,并且更重要的一点是基于 ThreadLocal 实现的 RequestContext 无法工作了。

 

对比2个版本,2.0的升级带来了20%的性能提升,Zuul 1.0可以承受百亿级别的流量,2.0则达到千亿级。相对而言,2.0并没有带来很大的性能提升,并且1.0版本已经可以满足大多业务需要,此外也可以通过使用 AsyncServlet 对1.0进行优化。因此选择1.0版本会更合适些。

 

参考资料

- https://github.com/Netflix/zuul/wiki/How-We-Use-Zuul-At-Netflix

- 杨波极客专栏《微服务架构实战160讲》

- http://www.ityouknow.com/springcloud/2018/01/20/spring-cloud-zuul.html

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章