前言
最近有个网友问了一个问题,zuul中如果两个filter的order一样,是如何排序的?引起了我的兴趣,特地去阅读了它的源码。
正文
zuul是干什么的
如果你有使用过springcloud应该听说过zuul,它的定位是分布式微服务中的API网关服务,当然后面可能要被gateway替代了。zuul是一个L7应用程序网关,提供了动态路由,监视,弹性,安全性等功能。zuul的大部分功能是通过filter实现的。
zuul定义了四种不同生命周期的filter
为了方便操作,zuul内置了一些filter,这些filter主要通过@EnableZuulServer
和@EnableZuulProxy
注解开启相关功能。@EnableZuulServer
注解开启的filter功能如下:
@EnableZuulProxy
注解除了开启上面这些filter功能之外,还开启了如下的功能:
如何自定义filter
只需继承ZuulFilter
类,实现它的filterType
、filterOrder
、shouldFilter
和 run
方法即可,具体实现可参考如下代码:
public class LogFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return 1; } @Override public boolean shouldFilter() { return RequestContext.getCurrentContext().sendZuulResponse(); } @Override public Object run() throws ZuulException { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); log.info("zuul pre filter-->" + request.getRequestURL() + "-->" + request.getMethod()); return null; } }
上面的四个方法有哪些作用呢?
方法名称 | 作用 |
filterType | filter类型,包含:pre、routing、post和error四种类型 |
filterOrder | 排序,该值越小,filter越早执行 |
shouldFilter | 开关,表示是否需要执行该filter |
run | filter具体的功能方法 |
需要注意的是,要想使zuul的功能生效,切记要在springboot启动类
上定义@EnableZuulServer
或@EnableZuulProxy
注解,表示开启zuul的功能。
filterOrder是如何排序的
先看看所有的zuulFilter在哪里执行的,谜底就在FilterProcessor
类的runFilters
方法中。
该方法很简单,先获取所有zuulFilter,然后遍历所有zuulFilter,调用processZuulFilter
方法执行具体的zuulFilter,然后将执行结果返回。
我们重点看看这个方法
FilterLoader.getInstance().getFiltersByType(sType);
该方法的具体逻辑
- 根据filterType从缓存中获取filter集合,如果缓存中有直接返回
- 如果缓存中没有,则创建filter集合,将所有filter中跟filterType的filter添加到filter集合中。
- 排序filter集合
- 将新创建的filter集合放入缓存。
从上面可以看出filter的排序是通过如下方法执行的:
Collections.sort(list);
该方法底层其实是通过list
的sort
方法实现的
看看ArrayList
的sort
方法,传入的Comparator
为null
它的底层又是通过Arrays
类的静态方法sort
实现的
由于上一步Comparator
为null,则会执行sort
方法。
该方法是通过ComparableTimSort
类的sort
方法实现的,这个方法是最核心的方法了
我们可以看到该方法其实是通过binarySort
二分查找排序的。
通过compareTo
方法比较大小。
我们回头再看看ZuulFilter
类
它实现了Comparable
接口,重写了compareTo
方法
所以,看到这里我们可以得出结论:ZuulFilter
是通过Integer
的compare
方法比较filterOrder
参数值大小来排序的。