zuul RequestContext filter原理

zuul是可以认为是一种API-Gateway。zuul的核心是一系列的filters, 其作用可以类比Servlet框架的Filter,或者AOP。其原理就是在zuul把Request route到源web-service的时候,处理一些逻辑,比如Authentication,Load Shedding等

==HttpRequest -> ‘pre’ filter -> ‘routing’ filter -> ‘post’ filter -> HttpResponse==

ZuulFilter主要特征如下:

Type:定义filter的类别,用字符串代表,有四种标准类别,代表了Request的生命周期。filterType()返回值代表该filter的Type。

PRE: 该类型的filters在Request routing到源web-service之前执行。用来实现Authentication、选择源服务地址等
ROUTING:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service。
POST:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端。
ERROR:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。
Execution Order: 同一个Type的filters组成Pipeline,Execution Order决定他们执行的顺序。filterOrder()返回值是该filter的Execution Order。

Criteria:定义了filter执行需要满足的条件。对应的方法是shouldFilter()
Action: 定了filter处理逻辑。对应的方法是run()。

ZuulServlet

zuul逻辑的入口是ZuulServlet.service(ServletRequest servletRequest, ServletResponse servletResponse)。

public void service(ServletRequest servletRequest, ServletResponse servletResponse)  {
            // 用于初始化RequestContext
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
            /* RequestContext 用于记录Request的context。前面也分析了,由于Servlet是单例多线程的,而Request由唯一 worker线程处理,这里的RequestContext使用`ThreadLocal`实现,其本身简单wrap了`ConcurrentHashMap`,*/
            RequestContext context = RequestContext.getCurrentContext();
            // 执行Pre filters逻辑
            preRoute();
            // 执行route逻辑
             route();
             // 执行postRoute逻辑
             postRoute();
    }

context使用ThreadLocal保存,这样每个worker线程都有一个与其绑定的RequestContext
三个核心的方法preRoute(),route(), postRoute(),zuul对request处理逻辑都在这三个方法里,ZuulServlet交给ZuulRunner去执行。由于ZuulServlet是单例,因此ZuulRunner也仅有一个实例。

ZuulRunner

ZuulRunner直接将执行逻辑交由FilterProcessor处理

FilterProcessor

public Object runFilters(String sType) throws Throwable {
        if (RequestContext.getCurrentContext().debugRouting()) {
            Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
        }
        boolean bResult = false;
        List list = FilterLoader.getInstance().getFiltersByType(sType);
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                ZuulFilter zuulFilter = list.get(i);
                Object result = processZuulFilter(zuulFilter);
                if (result != null && result instanceof Boolean) {
                    bResult |= ((Boolean) result);
                }
            }
        }
        return bResult;
    }
public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        long execTime = 0;
        String filterName = "";
        try {
            long ltime = System.currentTimeMillis();
            // 运行filter的处理逻辑
            ZuulFilterResult result = filter.runFilter();
            ExecutionStatus s = result.getStatus();
            execTime = System.currentTimeMillis() - ltime;
            // 记录filter的处理状态,如果filter处理失败,把异常抛出
            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);
                    break;
                default:
                    break;
            }
            if (t != null) throw t;
            usageNotifier.notify(filter, s);
            return o;
        } catch (Throwable e) {
          usageNotifier.notify(filter, ExecutionStatus.FAILED);
        }
    }
上面两段代码是FilterProcessor对filter的处理逻辑。

首先根据Type获取所有输入该Type的filter,List list。
遍历该list,执行每个filter的处理逻辑,processZuulFilter(ZuulFilter filter)
RequestContext对每个filter的执行状况进行记录,应该留意,此处的执行状态主要包括其执行时间、以及执行成功或者失败,如果执行失败则对异常封装后抛出。

总结

ZuulServlet是zuul框架的入口,其采用Servlet框架,是单例多线程,可以把它类比为SpringMVC的DispatcherServlet。ZuulServlet定义Request的生命周期内的处理逻辑,每个阶段的具体处理逻辑交由ZuulRunner和FilterProcessor。

你可能感兴趣的:(java_web)