(二)zuul源码-Zuul组件中相关的路由过滤器

2021-10-29  本文已影响0人  guessguess

那么如何给对应的请求找到处理器?

那么在讲查找过程的时候,需要去了解一下重要的接口。

重要的接口

ZuulFilterResult

用于存储ZuulFilter的执行结果

public final class ZuulFilterResult {
    private Object result;
    private Throwable exception;
    private ExecutionStatus status;
}

ZuulFilter

ZuulFilter过滤器接口
public interface IZuulFilter {
    //判断是否要拦截
    boolean shouldFilter();
    //运行
    Object run() throws ZuulException;
}
模板模式-核心实现。具体指定了ZuulFIlter的执行过程。
public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {
    过滤器的类型-分为pre post route error,由过滤器的子类去实现。
    abstract public String filterType();
    public ZuulFilterResult runFilter() {
        ZuulFilterResult zr = new ZuulFilterResult();
        需要开启过滤
        if (!isFilterDisabled()) {
            if (shouldFilter()) {
                Tracer t = TracerFactory.instance().startMicroTracer("ZUUL::" + this.getClass().getSimpleName());
                try {
                    Object res = run();
                    zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
                } catch (Throwable e) {
                    t.setName("ZUUL::" + this.getClass().getSimpleName() + " failed");
                    zr = new ZuulFilterResult(ExecutionStatus.FAILED);
                    zr.setException(e);
                } finally {
                    t.stopAndLog();
                }
            } else {
                zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
            }
        }
        return zr;
    }
}

FilterRegistry

这个类很简单,就是用于过滤器注册的。

public class FilterRegistry {
    private static final FilterRegistry INSTANCE = new FilterRegistry();
    public static final FilterRegistry instance() {
        return INSTANCE;
    }
    private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap<String, ZuulFilter>();
    private FilterRegistry() {
    }
    public ZuulFilter remove(String key) {
        return this.filters.remove(key);
    }
    public ZuulFilter get(String key) {
        return this.filters.get(key);
    }
    public void put(String key, ZuulFilter filter) {
        this.filters.putIfAbsent(key, filter);
    }
    public int size() {
        return this.filters.size();
    }
    public Collection<ZuulFilter> getAllFilters() {
        return this.filters.values();
    }
}

FilterLoader

这个类其实就是用来存储过滤器以及对过滤器分类,以及加载过滤器的。

public class FilterLoader {
    final static FilterLoader INSTANCE = new FilterLoader();
    private final ConcurrentHashMap<String, Long> filterClassLastModified = new ConcurrentHashMap<String, Long>();
    private final ConcurrentHashMap<String, String> filterClassCode = new ConcurrentHashMap<String, String>();
    private final ConcurrentHashMap<String, String> filterCheck = new ConcurrentHashMap<String, String>();
    private final ConcurrentHashMap<String, List<ZuulFilter>> hashFiltersByType = new ConcurrentHashMap<String, List<ZuulFilter>>();
    private FilterRegistry filterRegistry = FilterRegistry.instance();
}

FilterProcessor

<span id="FilterProcessor">FilterProcessor的runFilters方法</span>
这个类就是过滤器处理器,其实zuul处理请求都是通过过滤器的形式去处理的。
最重要的地方在于定义了如何利用过滤器去执行请求。

public class FilterProcessor {
    static FilterProcessor INSTANCE = new FilterProcessor();
    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 = list.get(i);
                Object result = processZuulFilter(zuulFilter);
                if (result != null && result instanceof Boolean) {
                    bResult |= ((Boolean) result);
                }
            }
        }
        return bResult;
    }
}

1.Zuul组件如何实现动态过滤?

Zuul组件如何实现动态过滤

2.Zuul相关过滤器的注册以及作用

其实在前面已经知道,Zuul是以过滤器的方式来运行的。从FilterProcessor的runFilters方法得知代码点击此处
那么Zuul有什么类型的过滤器?

Pre-路由前需要执行的过滤器(其实就是路由前需要做的操作)

org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter
org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter
org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter
org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter
org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter

Route-路由时执行的过滤器(其实就是路由时需要做的操作)

org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter
org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter
org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter

Post-路由后执行的过滤器(其实就是路由后需要做的操作)

org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter

Error-发送错误时执行的过滤器

org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter

以上的过滤器的注册时机

源码如下

public class ZuulFilterInitializer {
    @PostConstruct
    public void contextInitialized() {
        log.info("Starting filter initializer");

        TracerFactory.initialize(tracerFactory);
        CounterFactory.initialize(counterFactory);

        for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
            filterRegistry.put(entry.getKey(), entry.getValue());
        }
    }
}

由于最后根据类型获取的时候会进行分类以及排序(order值越小,执行的优先级越高)。最后对应的过滤器链如下

pre-org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter  
      org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter
      org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter
      org.springframework.cloud.netflix.zuul.filters.pre.DebugFilte
      org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter
route- org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter
          org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter
          org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter
post- org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter
error-org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter

Route类型的过滤器的作用

由于Pre 以及 Post其实作用都很明显了,就不去了解了。因为其实最主要的是关心如何去路由。
以下是route类型的过滤器的执行顺序。

RibbonRoutingFilter

RibbonRoutingFilter的拦截方法

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return (ctx.getRouteHost() == null && ctx.get(SERVICE_ID_KEY) != null
                && ctx.sendZuulResponse());
    }

对应的路由规则
application.yml中的配置

zuul:
  routes:
    advice1: 随便取个名字 路由规则1  
      path: /client/xxx  请求路径
      serviceId: client  映射到的服务Id

所以这里很清晰明了,只要RequestContext中包含service-id且没有route-host,就会被RibbonRoutingFilter拦截。

SimpleHostRoutingFilter

SimpleHostRoutingFilter的拦截方法

    @Override
    public boolean shouldFilter() {
        return RequestContext.getCurrentContext().getRouteHost() != null
                && RequestContext.getCurrentContext().sendZuulResponse();
    }

application.yml中的配置

zuul:
  routes:
    advice2:
      path: /client/xxx
      url: https://www.jianshu.com/

只要有route-host就会被SimpleHostRoutingFilter处理

SendForwardFilter
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.containsKey(FORWARD_TO_KEY)
                && !ctx.getBoolean(SEND_FORWARD_FILTER_RAN, false);
    }

配置如下

zuul:
  routes:
    advice3:
      path: /client/xxx
      url: forward:/b
路由的过程如下

对于一个请求的处理,是pre,route,post。
pre以及Post的执行过程也是一样的。只不过执行的过滤器链不一样。

上一篇下一篇

猜你喜欢

热点阅读