Zuul源码分析
Posted south-pigeon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zuul源码分析相关的知识,希望对你有一定的参考价值。
zuul:
用户访问zuul回首先进入zuul的什么东西里面?
用户访问SpringMvc会先进那里?DispathchServlet
在zuul里面也有一个请求转发器,ZuulServlet
源码:
ZuulServlet继承HttpServlet
public class ZuulServlet extends HttpServlet {}
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { try { this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
// 所有的请求都建立 RequestContext context = RequestContext.getCurrentContext();
// 给当前的访问,设置一个zuul的处理引擎 context.setZuulEngineRan(); try {
// 先进入pre的Router,会执行系统里面的所有的ZuulFilter
// preRoute主要做参数的校验,权限验证,限流等 this.preRoute(); } catch (ZuulException var12) {
// 若在preRoute期间发生错误,则先进入Error的filter,其次进入postRoute,因为postRoute才能给用户响应数据 this.error(var12); this.postRoute(); return; } try {
// zuul将用户的访问,转为由zuul构造请求去访问微服务 this.route(); } catch (ZuulException var13) { this.error(var13); this.postRoute(); return; } try {
// zuul将微服务响应给它的数据,响应给用户 this.postRoute(); } catch (ZuulException var11) { this.error(var11); } } catch (Throwable var14) { this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } }
preRoute()
void preRoute() throws ZuulException {
// servlet交给ZuulRunner去执行过滤器 this.zuulRunner.preRoute(); }
zuulRunner里面的preRoute()
runner里面并没有做实际的事情,交给FilterProcessor
public void preRoute() throws ZuulException { FilterProcessor.getInstance().preRoute(); }
真正的执行方法
public void preRoute() throws ZuulException { try { this.runFilters("pre"); } catch (ZuulException var2) { throw var2; } catch (Throwable var3) { throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + var3.getClass().getName()); } }
public Object runFilters(String sType) throws Throwable { if (RequestContext.getCurrentContext().debugRouting()) { Debug.addRoutingDebug("Invoking {" + sType + "} type filters"); } boolean bResult = false;
// 通过过滤器加载器,获取所有该类型的过滤器 ‘pre‘ List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType); if (list != null) { for(int i = 0; i < list.size(); ++i) { ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
// 执行每个过滤器 Object result = this.processZuulFilter(zuulFilter); if (result != null && result instanceof Boolean) { bResult |= (Boolean)result; } } } return bResult; }
public Object processZuulFilter(ZuulFilter filter) throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); boolean bDebug = ctx.debugRouting(); String metricPrefix = "zuul.filter-"; long execTime = 0L; String filterName = ""; try { long ltime = System.currentTimeMillis(); filterName = filter.getClass().getSimpleName(); RequestContext copy = null; Object o = null; Throwable t = null; if (bDebug) { Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName); copy = ctx.copy(); } // 实际执行的filter ZuulFilterResult result = filter.runFilter(); ExecutionStatus s = result.getStatus(); execTime = System.currentTimeMillis() - ltime; switch(s) { case FAILED: t = result.getException(); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); break; case SUCCESS: o = result.getResult(); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime); if (bDebug) { Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms"); Debug.compareContextState(filterName, copy); } } if (t != null) { throw t; } else { this.usageNotifier.notify(filter, s); return o; } } catch (Throwable var15) { if (bDebug) { Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + var15.getMessage()); } this.usageNotifier.notify(filter, ExecutionStatus.FAILED); if (var15 instanceof ZuulException) { throw (ZuulException)var15; } else { ZuulException ex = new ZuulException(var15, "Filter threw Exception", 500, filter.filterType() + ":" + filterName); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); throw ex; } } }
public ZuulFilterResult runFilter() { ZuulFilterResult zr = new ZuulFilterResult(); if (!this.isFilterDisabled()) { if (this.shouldFilter()) { Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName()); try {
// 执行filter里面的拦截方法 Object res = this.run(); zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS); } catch (Throwable var7) { t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed"); zr = new ZuulFilterResult(ExecutionStatus.FAILED); zr.setException(var7); } finally { t.stopAndLog(); } } else { zr = new ZuulFilterResult(ExecutionStatus.SKIPPED); } } return zr; }
public interface IZuulFilter { boolean shouldFilter(); Object run() throws ZuulException; }
zuul执行流程总结
ZuulServlet->ZuulServlet.xxxRouter->ZuulRunner.xxxRouter->FileterProcessor.getInstance().xxxRouter()
主要执行Filter的代码在filterProcessor里面完成
1. 加载执行类型的Filter列表
List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
2. 执行每个FIleter
FilterProcessor.processZullFilter(Filter)->Filter.runFilter->Filter.run()
以上是关于Zuul源码分析的主要内容,如果未能解决你的问题,请参考以下文章