zuul简介(一)

来源:互联网 发布:域名访问tomcat项目 编辑:程序博客网 时间:2024/05/29 02:09
zuul简介

Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。
Zuul的内部实现结构图如下:

 Zuul提供了一个框架,可以对过滤器进行动态的加载,编译,运行。过滤器之间没有直接的相互通信。他们是通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。

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

下面有几种标准的过滤器类型:

  • PRE:这种过滤器在请求到达Origin Server之前调用。比如身份验证,在集群中选择请求的Origin Server,记log等。
  • ROUTING:在这种过滤器中把用户请求发送给Origin Server。发送给Origin Server的用户请求在这类过滤器中build。并使用Apache HttpClient或者Netfilx Ribbon发送给Origin Server。
  • POST:这种过滤器在用户请求从Origin Server返回以后执行。比如在返回的response上面加response header,做各种统计等。并在该过滤器中把response返回给客户。
  • ERROR:在其他阶段发生错误时执行该过滤器。
  • 客户定制:比如我们可以定制一种STATIC类型的过滤器,用来模拟生成返回给客户的response。

过滤器的生命周期如下所示:


Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

  • 验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。
  • 审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。
  • 动态路由: 以动态方式根据需要将请求路由至不同后端集群处。
  • 压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。
  • 负载分配: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。
  • 静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。
  • 多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。

除此之外,Netflix公司还利用Zuul的功能通过金丝雀版本实现精确路由与压力测试。

 

其核心代码ZuulServletFilter为:


@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {    try {        init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);        try {            preRouting();        } catch (ZuulException e) {            error(e);            postRouting();            return;        }                // Only forward onto to the chain if a zuul response is not being sent        if (!RequestContext.getCurrentContext().sendZuulResponse()) {            filterChain.doFilter(servletRequest, servletResponse);            return;        }                try {            routing();        } catch (ZuulException e) {            error(e);            postRouting();            return;        }        try {            postRouting();        } catch (ZuulException e) {            error(e);            return;        }    } catch (Throwable e) {        error(new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_FROM_FILTER_" + e.getClass().getName()));    } finally {        RequestContext.getCurrentContext().unset();    }}

Zuul加载Groovy过滤器:
package com.netflix.zuul.groovy;import com.netflix.zuul.DynamicCodeCompiler;import groovy.lang.GroovyClassLoader;import groovy.lang.GroovyObject;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.runners.MockitoJUnitRunner;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.File;import java.io.IOException;import static org.junit.Assert.*;import static org.mockito.Mockito.spy;/** * Groovy code compiler * User: mcohen * Date: 5/30/13 * Time: 11:38 AM * To change this template use File | Settings | File Templates. */public class GroovyCompiler implements DynamicCodeCompiler {    private static final Logger LOG = LoggerFactory.getLogger(GroovyCompiler.class);    /**     * Compiles Groovy code and returns the Class of the compiles code.     *     * @param sCode     * @param sName     * @return     */    @Override    public Class compile(String sCode, String sName) {        GroovyClassLoader loader = getGroovyClassLoader();        LOG.warn("Compiling filter: " + sName);        Class groovyClass = loader.parseClass(sCode, sName);        return groovyClass;    }    /**     * @return a new GroovyClassLoader     */    GroovyClassLoader getGroovyClassLoader() {        return new GroovyClassLoader();    }    /**     * Compiles groovy class from a file     *     * @param file     * @return     * @throws java.io.IOException     */    @Override    public Class compile(File file) throws IOException {        GroovyClassLoader loader = getGroovyClassLoader();        Class groovyClass = loader.parseClass(file);        return groovyClass;    }    @RunWith(MockitoJUnitRunner.class)    public static class UnitTest {        @Test        public void testLoadGroovyFromString() {            GroovyCompiler compiler = spy(new GroovyCompiler());            try {                String code = "class test { public String hello(){return \"hello\" } } ";                Class clazz = compiler.compile(code, "test");                assertNotNull(clazz);                assertEquals(clazz.getName(), "test");                GroovyObject groovyObject = (GroovyObject) clazz.newInstance();                Object[] args = {};                String s = (String) groovyObject.invokeMethod("hello", args);                assertEquals(s, "hello");            } catch (Exception e) {                assertFalse(true);            }        }    }}



参考:
Netflix学习笔记:Zuul - lxlong - ITeye博客
独立使用zuul网关分发不同服务的请求、权限控制,非SpringCloud - tianyaleixiaowu的专栏 - CSDN博客
springcloud----Zuul动态路由 - 徐靖峰的专栏 - CSDN博客
使用zuul及oauth2构建api网关实践之路 - 简书
Spring Cloud入门教程(六):API服务网关(Zuul) 下 - 简书
zuul学习一:spring cloud zuul的快速入门 - 简书
zuul学习二:zuul路由详解(一) - 简书
zuul学习三:zuul路由详解(二) - 简书
zuul学习四:zuul 过滤器详解 - 简书
zuul学习五:zuul 异常处理 - 简书
zuul学习六:禁用过滤器 - 简书

流控