笔记:Zuul Core 源码阅读

发布 : 2020-09-03

笔记:Zuul Core 源码阅读

架构图

流程的解析

全局的入口 ZuulServlet

  • Zuul 只有一个全局的 servlet 因此对于所有发送到Zuul 的请求都将会由这个 servlet 解析。我们知道每个servlet 只会实例化一次,每次请求都会调用 ZuulServlet 的 service 方法。

  • ZuulServlet 内部的 ZuulRunner 并不是静态变量,但是正如上面提到的。servlet 变量只有一个因此,并不需要反复的初始化 servlet。本质上 ZuulRunner 对于 Zuul 网关来说也是单例的。

过滤器链 与 异常处理

  • ZuulServlet 内部会调用 ZuulRunnner.pre() ZuulRunner.route() ZuulRunnner.post() 并以TRY CATCH 的形式完成 pre-route-post 或者在有异常的情况下存在,实现 pre-error-post ,pre-route-err-post ,pre-route-post-error 的形式。

  • 注意到采用finally的设计,即使不同的线程service存在问题,也可以在最后把 RequestContext 移除。

  • 若代码抛出 ZuulException 代表代码中产生的异常是可以捕获且可以处理的。而如果是其他异常直接捕获 throwable 类,保证不会因为一个线程的问题影响到整个系统。

  • 过滤器链条实现了责任链模式,通过不同的过滤器链条来实现。且通过一个基于 ThreadLocal 中存储 RequestContext Map 这样一个数据结构完成不同的过滤器链条的设计。可以看出不同的过滤器链条在设计上并不耦合增加了可扩展性。但是让代码不容易阅读。

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
try {
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
RequestContext context = RequestContext.getCurrentContext();
context.setZuulEngineRan();

try {
preRoute();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
route();
} catch (ZuulException e) {
error(e);
postRoute();
return;
}
try {
postRoute();
} catch (ZuulException e) {
error(e);
return;
}

} catch (Throwable e) {
error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}

RequestContext

  1. RequestContext 继承了 ConcurrentHashMap。RequestContext 重写了 ThreadLocal 的initialValue 方法,在调用use时自动的完成了初始化。

  2. RequestContext 采用 getCurrentContext 方法去获取当前线程存储的 ThreadLocal的 RequestContext。

  3. 这里有个问题,RequestContext既然已经是ThreadLocal 了。意味着本身这个RequestContext 就是线程安全的。所以问为什么需要继承 ConcurrentHashMap 呢?

本文作者 : Rothleer
原文链接 : https://rothleer.github.io/2020/09/03/%E7%AC%94%E8%AE%B0%EF%BC%9AZuul%20Core%20%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

博客已萌萌哒运行(●'◡'●)ノ♥
Theme - BMW | Made With 💗 | Powered by GodBMW