美文网首页
(二)zuul源码-Zuul组件中相关的路由过滤器

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

作者: guessguess | 来源:发表于2021-10-29 16:13 被阅读0次

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

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

重要的接口

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的执行过程也是一样的。只不过执行的过滤器链不一样。

相关文章

  • SpringCloudZull.md

    一、zuul的特点: 路由+过滤器 =zuul 核心是一系列过滤器 二、zuul的四中过滤器API 前置(pre)...

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

    那么如何给对应的请求找到处理器? 那么在讲查找过程的时候,需要去了解一下重要的接口。 重要的接口 ZuulFilt...

  • Zuul的小节

    一、Zuul前置过滤器的作用 二、Zuul后置过滤器的作用 三、Zuul的高可用

  • Zuul路由网关与过滤器

    技术需求点:1.介绍Zuul网关路由和过滤器两大功能的工作原理;2.模拟Zuul路由网关功能;3.使用Zuul网关...

  • Zuul源码分析

    目标 明确Zuul的执行流程和重要类的分析 Zuul过滤器的生命周期 源码分析 zuul怎么拦截我们的请求? Zu...

  • 2018-07-07

    Zuul--学习笔记(5) 目录一、参考Spring Cloud官方文档--1、路由器和过滤器:Zuul--2、如...

  • spring cloud 学习笔记二

    路由网关 zuul Zuul的主要功能是路由和过滤器。路由功能是微服务的一部分,比如/api/user映射到use...

  • API网关服务Zuul-Spring Cloud学习第五天(非原

    文章大纲 一、Zuul是什么二、Zuul的基本实现三、路由配置细节四、异常处理细节五、项目源码与参考资料下载六、参...

  • 服务网关Spring Cloud Zuul

    一、Zuul简介 Zuul作为微服务系统的网关组件,用于构建边界服务(Edge Service),致力于动态路由、...

  • zuul之请求处理流程

    目录 zuul之请求处理流程 zuul之动态过滤器Filter类文件管理加载 zuul之过滤器Filter管理 概...

网友评论

      本文标题:(二)zuul源码-Zuul组件中相关的路由过滤器

      本文链接:https://www.haomeiwen.com/subject/mxcpaltx.html