网关zuul——过滤器
Posted awsl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网关zuul——过滤器相关的知识,希望对你有一定的参考价值。
网关——过滤器
从网关组件请求流程分析,可以看出网关的核心类为ZuulServlet,所有的请求都是走到这里来处理的!
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { try { this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse); RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { this.preRoute(); } catch (ZuulException var12) { this.error(var12); this.postRoute(); return; } try { this.route(); } catch (ZuulException var13) { this.error(var13); this.postRoute(); return; } try { 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(); } }
从service方法中可以看出,preRoute()、route()、postRoute()、error()这4个方法为一套模板方法,定义了整个zuul组件的处理规则:
先执行preRoute()、再执行route(),然后是postRoute(),当任意环节出问题时,走到error()方法。
void postRoute() throws ZuulException { this.zuulRunner.postRoute(); } void route() throws ZuulException { this.zuulRunner.route(); } void preRoute() throws ZuulException { this.zuulRunner.preRoute(); } void error(ZuulException e) { RequestContext.getCurrentContext().setThrowable(e); this.zuulRunner.error(); }
从上述代码可以看出,实际执行这套模板方法的时zuulRunner类
这次以preRoute()方法为例进行分析,最终preRoute()
在ZuulRunner中,调用的是FilterProcessor实例的preRoute();FilterProcessor类为单例模式,同时看其类名就可以知道该类是过滤器处理类;
public void preRoute() throws ZuulException { FilterProcessor.getInstance().preRoute(); }
查看在FilterProcessor类中preRoute()的具体实现
public void preRoute() throws ZuulException { try { //这里是运行指定类型的过滤器 //只有类型为pre的过滤器才会被调用 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; 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).booleanValue(); } } } return bResult; }
processZuulFilter(Zuulfilter filter)的具体内容
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(); } // 主要内容 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; } }
runFilter()中的内容
public ZuulFilterResult runFilter() { ZuulFilterResult zr = new ZuulFilterResult(); if (!this.isFilterDisabled()) { //判断是否执行filter if (this.shouldFilter()) { Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName()); try { //执行filter中的run方法 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; }
从上面代码可以看出,preRoute()方法为运行类型为”pre“的过滤器;从runFilter()方法可以看出,只有过滤器需要执行时才会执行过滤器中的run()方法;即过滤器中的run方法中包含了所有的过滤器要做的所有业务。
其他route(),postRoute(),error()中的代码也遵循这一规则,只有过滤器类型不同这一点
总结:
网关组件Zuul中的过滤器:
在ZuulServlet中的service方法中定义过滤器的执行顺序,按preRoute()、route()、postRoute()顺序执行,error()时在出现异常时的处理规则。
追踪preRoute()方法的执行可以得知,preRoute()经过了这3个类:ZuulServlet——>ZuulRunner——>FilterProcessor;
最终preRoute的具体实现规则是在FilterProcessor中定义的
在runFilters中定义了过滤器的类型:pre、route、post、error
在ZuulFilter抽象类中的runFilter定义了过滤器是否被执行以及执行的方法体为run()方法
综上,要想添加一个能在网关中使用的自定义的过滤器;必须继承ZuulFilter抽象类,同时在filterType方法中定义好过滤器类型:pre、route、post、error;shouldFilter方法必须返回true才能执行,过滤器的具体实现逻辑要定义在run()方法中。
以上是关于网关zuul——过滤器的主要内容,如果未能解决你的问题,请参考以下文章