zuul简介(一)

本文详细介绍了Zuul作为云平台边缘服务框架的作用,包括动态路由、监控、安全等功能。阐述了Zuul的内部结构,过滤器的工作原理及其生命周期,并展示了核心代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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为:


@Override
public 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);
            }

        }
    }
}



参考:




03-08
### Zuul 微服务网关使用指南 #### Zuul简介 Zuul 是 Netflix 开源的款基于 JVM 的路由器和服务器端负载均衡器,能够帮助开发者轻松实现动态路由、监控、弹性和安全性等功能。作为微服务架构中的重要组成部分之Zuul 可以为整个系统的流量管理和访问控制提供强大的支持。 #### 二、基本功能特性 - **请求过滤**:可以在请求到达实际业务逻辑之前对其进行预处理或修改响应数据。 - **路由转发**:根据不同的条件将客户端请求分发给对应的服务实例。 - **熔断机制**:当某个下游依赖出现问题时自动触发保护措施防止连锁反应影响其他模块正常工作。 - **性能优化**:通过对热点接口实施缓存策略来减少重复计算提高整体效率[^1]。 #### 三、配置示例 为了使 Zuul 成功地与 Zipkin 结合并记录下每次 HTTP 请求的日志以便后续分析诊断问题所在,则需按照如下方式调整 application.yml 文件内的参数设置: ```yaml zuul: ignoredServices: '*' # 忽略所有默认注册的服务 routes: orderservice: # 自定义路径映射关系 path: /order/** serviceId: order-service ribbon: eureka: enabled: true # 启用Ribbon配合Eureka完成服务发现过程 sleuth: sampler: probability: 1.0 # 设置采样率为百分之百确保每条链路都能被跟踪到 zipkin: baseUrl: http://localhost:9411/ # 指定Zipkin Server地址用于上传追踪信息 ``` 上述 YAML 片段展示了如何让 Zuul 网关的请求追踪信息成功发送至 Zipkin 服务器,并可通过后者提供的图形界面查看详细的调用链条情况。 #### 四、实战案例分享 假设现在有个电子商务平台项目,其中包含了多个独立部署的小型应用程序(即所谓的“微服务”),例如负责处理商品展示的商品服务、管理用户账户的信息服务以及执行支付操作的交易服务等等。此时就可以利用 Zuul 来充当统入口角色,把来自外部世界的各种请求合理分配出去,从而简化前端开发人员的工作量同时也增强了后端系统的灵活性和可维护性[^2]。 对于像订单这样的核心业务流程而言,可以将其关联的所有 RESTful API 接口都集中托管在个专门设计好的子系统内部;而对于涉及敏感数据的操作则建议单独设立权限验证层以保障信息安全不受侵犯。此外还可以考虑引入诸如 Hystrix 这样的第三方库进步增强应用本身的容错能力和自愈能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值