zuul 1.x 源码阅读之 ZuulServlet 及 Filter 加载

原创: http://www.imet.me/post/2018/07-03_zuul_1.x_source/

zuul 是什么,为什么需要 zuul,zuul 实现原理?

一、zuul overview

1.1 什么是 Zuul?

zuul 作为云服务的边界服务(Edge Service),可以用来做统一授权、压力测试、金丝雀测试(Canary Testing)、动态路由、减负载以及和 netflix 其他套件一起协作

1.2 zuul as edge service

直接用官方用图:

Zuul in Netflix’s Cloud Architecture

如上图,zuul 处于内部服务的入口,起到边界服务(Edge Service)的作用

1.3 zuul 的工作原理

先不解释看官方图:

Zuul Core Architecture

分析一下 zuul 的思路:

  1. ZuulServlet: zuul 的核心其实就是 ZuulServlet, 在 NIO 之前, java web 服务都是以 Servlet 作为入口提供服务的。
  2. ZuulFilter Runner: 通过 Runner 来串起来不同类型的 filter, 一个 http request 经过 “pre”, “route”, “post” 这三种类型的 filter。有点 servlet filter 的味道
  3. Filter: 可以在 Filter 里执行业务需要的逻辑。Filter 支持 java 类型的 filter 和 groovy 类型的 filter
  4. Filter Loader: 如果要做到动态添加或者移除 filter 的话,groovy 脚本动态编译是个不错的选择。通过监听指定目录,然后生成 filter 类,装载到 zuul runner
  5. Request Context: filter 如何获取 http request/response 呢。猜对了,ThreadLocal, 通过把 HttpRequest 和 HttpResposne Wrapper 起来,放到 threadlocal 变量里。

二、zuul-core + zuul-simple-webapp 源码解读之 ZuulServlet

先跑起工程再说,跑起 zuul-simple-webapp 工程,参考官方wiki

2.1 web.xml 声明

web.xml 声明完成了以下几件事情:

  • StartServer(ServletContextListener): 是 web 容器的监听器,在容器 context 初始化时做了以下几件事情:

    1. mock monitor
    2. 初始化 FilterFileManager: 去系统变量 zuul.filter.root 目录下定时检查是否有新的脚本
    3. 初始化 JavaFilter
  • ZuulServlet: 是 Servlet 时代处理 http 请求的主要主体。我们源码会分析

  • ContextLifecycleFilter: 主要是及时清理 threadLocal 相关的变量: ZuulServlet 为了使 ZuulFilter 能获取Request相关的 Context, 把 requestContext 放到 threadlocal 中。

<listener>
    <listener-class>com.netflix.zuul.StartServer</listener-class>
</listener>

<servlet>
    <servlet-name>Zuul</servlet-name>
    <servlet-class>com.netflix.zuul.http.ZuulServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>Zuul</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>ContextLifecycleFilter</filter-name>
    <filter-class>com.netflix.zuul.context.ContextLifecycleFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ContextLifecycleFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2.2 ZuulServlet

a.) ZuulServlet 是继承 HttpServlet

通过实现 Servlet 的 initservic 来分别完成初始化和处理 http 逻辑。

b.) init 方法中创建 ZuulRunner 对象。
  1. 查看 Config param 里是否包含 buffer-requests
  2. ZuulServlet 的实际执行都是在 ZuulRunner 去处理的
c.) service 方法干了以下几件事情
  • 通过 ZuulRunner 初始化 request

.ZuulRunner.java

public void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
    
  // 主要就是把 request 和 resposne 放到 requestContext 的 ThreadLocal 变量里
  RequestContext ctx = RequestContext.getCurrentContext();
  if (bufferRequests) {
    
      ctx.setRequest(new HttpServletRequestWrapper(servletRequest));
  } else {
    
      ctx.setRequest(servletRequest);
  }

  ctx.setResponse(new HttpServletResponseWrapper(servletResponse));
}
  • RequestContext 是以 ConcurrentHashMap 来存储 http 请求中 header,body 等各种参数的
  • 同时通过 RequestContext.getCurrentContext() 来获取 threadlocal 中的 context

.RequestContext.java

public class RequestContext extends ConcurrentHashMap<String, Object> {
    

    protected static Class<? extends RequestContext> contextClass = RequestContext.class;

    private static RequestContext testContext = null;

    protected 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值