SpringCloud-Zuul(二):自定义Filter及内部路由源码解析

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-01 14:16:57

本文原创地址,我的博客https://jsbintask.cn/2019/04/03/springcloud/springcloud-zuul-customfilters/(食用效果最佳),转载请注明出处!

前言

上一篇介绍了SpringCloud使用Zuul的调用流程,明白了Zuul的工作原理关键在于ZuulServlet和它的内置Filter,所以在实际工作中,编写业务逻辑的关键就在于自定义filter。

用法

实现ZuulFilter

实现一个自定义Filter很简单,继承自ZuulFilter即可:

@Component public class Filter extends ZuulFilter {     @Override     public String filterType() {         return "pre";     }      @Override     public int filterOrder() {         return 0;     }      @Override     public boolean shouldFilter() {         return true;     }      @Override     public Object run() throws ZuulException {         RequestContext context = RequestContext.getCurrentContext().getRequest();         HttpServletRequest request = context.getRequest();         HttpServletResponse response = context.getResponse();         System.out.println("Filter.run");         return null;     } } 
  1. filterType方法返回filter类型
  2. filterOrder返回同类型filter执行顺序
  3. shouldFilter返回请求是否应该执行run方法。
  4. run表示业务逻辑执行过程。
  5. 处理逻辑过程中如果需要用到HttpServletRequest和HttpServletResponse可以用RequestContext.getCurrentContext()拿出。

Filter类型

Zuul的Filter一共分为四个种类,Pre,Route,Post,Error,每种Filter的执行时机不同,所以他们在业务逻辑功能上有所不同,如图:

  1. Pre类型的Filter总是先执行,它可以做限流,权限控制等。
  2. Route类型的Filter为Zuul内部转发请求到真正的服务的Filter,一般我们不需要实现这种类型.
  3. Post为请求转发完成后的后续动作,可以进行日志等的一些添加。
  4. Error为上述Filter出错后执行的动作,可以进行错误处理等。
    关于它们的执行顺序,如图:

源码解析

zuul内部已经定义了各种类型的filter,如预处理,路由转发,错误处理等。我们可以通过源码来研究Zuul是如何帮我们转发请求的:

  1. RibbonRoutingFilter
  2. SimpleHostRoutingFilter
  3. SendForwardFilter
    上面三个Filter只会执行一个,控制它们执行过程的为PreDecorationFilter:


    当整合的是微服务时,则配置的为服务名,如:
zuul:   prefix: /api   routes:     espay-auth:       path: /test/**       service-id: service-name 

这个时候将调用RibbonRoutingFilter作负载均衡转发请求:

protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception {     Map<String, Object> info = this.helper.debug(context.getMethod(),             context.getUri(), context.getHeaders(), context.getParams(),             context.getRequestEntity());      RibbonCommand command = this.ribbonCommandFactory.create(context);     try {         ClientHttpResponse response = command.execute();         this.helper.appendDebug(info, response.getRawStatusCode(), response.getHeaders());         return response;     }     catch (HystrixRuntimeException ex) {         return handleException(info, ex);     } } 

而当我们配置的直接为某个地址:

zuul:   routes:     espay-auth:       path: /auth/**       url: http://baidu.com 

则会调用SimpleHostRoutingFilter进行转发,它内部直接使用HttpClient进行转发:


而当请求出错时,则会交由SendErrorFilter处理,它会设置标志位SEND_ERROR_FILTER_RAN为true,然后重新发送请求到PreDecorationFilter。这个时候的流程为:


SendForwardFilter:


这样一次完整的路由,转发,错误处理就分析完毕。

总结

  1. Zuul内部使用自定义filter处理业务逻辑。
  2. Zuul内部有四种不同类型的Filter。
  3. Zuul内部转发请求有两种,为服务下边的RibbonRoutingFilter,普通http转发的SimpleHostRoutingFilter.

关注我,这里只有干货!

相关文章:
SpringCloud-Zuul(一):技术选型及请求流程源码走读

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!