浅谈SpringCloud之zuul源码解析

 更新时间:2018年02月22日 16:45:11   作者:小兵成长记  
这篇文章主要介绍了浅谈SpringCloud之zuul源码解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

zuul各版本实现存在一些微小的变化,总的实现思想未改变,以spring-cloud-netflix-core-1.3.6.RELEASE为例

一、zuul的重要的初始化类

org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration

org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration

org.springframework.cloud.netflix.zuul.ZuulFilterInitializer

org.springframework.cloud.netflix.zuul.RibbonCommandFactoryConfiguration

ZuulServerAutoConfiguration

初始化路由规则

初始化一些重要的filter如 PreDecorationFilter,RibbonRoutingFilter

初始化ZuulFilterInitializer

初始化ZuulHandlerMapping

代码如下

 //路由规则
  @Bean
 @ConditionalOnMissingBean(DiscoveryClientRouteLocator.class)
 public DiscoveryClientRouteLocator discoveryRouteLocator() {
 return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties,
  this.serviceRouteMapper);
 }
   
 // pre filters
 @Bean
 public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) {
 return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), this.zuulProperties,
  proxyRequestHelper);
 }

 // route filters
 @Bean
 public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,
  RibbonCommandFactory<?> ribbonCommandFactory) {
 RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers);
 return filter;
 }

  @Configuration
 protected static class ZuulFilterConfiguration {

 @Autowired
 private Map<String, ZuulFilter> filters;

 @Bean
 public ZuulFilterInitializer zuulFilterInitializer(
  CounterFactory counterFactory, TracerFactory tracerFactory) {
  FilterLoader filterLoader = FilterLoader.getInstance();
  FilterRegistry filterRegistry = FilterRegistry.instance();
  return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry);
 }

 }
 @Bean
 public ZuulController zuulController() {
 return new ZuulController();
 }

 @Bean
 public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
 ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());
 mapping.setErrorController(this.errorController);
 return mapping;
 }

ZuulProxyAutoConfiguration

zuulProxAutoConfiguration继承ZuulServerAutoConfiguration功能上和zuulServerAutoConfiguration

主要功能是增加了RibbonCommandFactoryConfiguration的配置,初始化所有的实现ribbon的方式如apache,okhttp。

ZuulFilterInitializer

该类的作用主要是把初始化的过滤器注册到zuul的FilterRegistry,FilterRegistry是一个单例用于初始化路由信息,在ZuulRunner中使用

RibbonCommandFactoryConfiguration

  主要作用是配置转发的实现,实现主要有apache,okhttp

二、zuul的转发实现

首先第一步转到ZuulHandlerMapping中的lookupHandler方法,把转发转到zuulController中

@Override
 protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
 if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) {
  return null;
 }
 String[] ignored = this.routeLocator.getIgnoredPaths().toArray(new String[0]);
 if (PatternMatchUtils.simpleMatch(ignored, urlPath)) {
  return null;
 }
 RequestContext ctx = RequestContext.getCurrentContext();
 if (ctx.containsKey("forward.to")) {
  return null;
 }
 if (this.dirty) {
  synchronized (this) {
  if (this.dirty) {
   registerHandlers();
   this.dirty = false;
  }
  }
 }
 return super.lookupHandler(urlPath, request);
 }

第一次访问时dirty为true会初始化一次请求规则如下

private void registerHandlers() {
 Collection<Route> routes = this.routeLocator.getRoutes();
 if (routes.isEmpty()) {
  this.logger.warn("No routes found from RouteLocator");
 }
 else {
  for (Route route : routes) {
  registerHandler(route.getFullPath(), this.zuul);
  }
 }
 }

第二步ZuulController继承ServletWrappingController的会把请求转到ZuulServlet中如下

/**
 * @author Spencer Gibb
 */
public class ZuulController extends ServletWrappingController {
 public ZuulController() {
 setServletClass(ZuulServlet.class);
 setServletName("zuul");
 setSupportedMethods((String[]) null); // Allow all
 }

 @Override
 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
 try {
  // We don't care about the other features of the base class, just want to
  // handle the request
  return super.handleRequestInternal(request, response);
 }
 finally {
  // @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
  RequestContext.getCurrentContext().unset();
 }
 }
}

第三步ZuulServlet的service方法如下主要执行pre,route,postRoute三种路由器

 @Override
  public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
    try {
      init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
      // Marks this request as having passed through the "Zuul engine", as opposed to servlets
      // explicitly bound in web.xml, for which requests will not have the same data attached
      RequestContext context = RequestContext.getCurrentContext();
      context.setZuulEngineRan();
      try {
        preRoute();
      } catch (ZuulException e) {
        error(e);
        postRoute();
        return;
      }
      try {
        route();
      } catch (ZuulException e) {
        error(e);
        postRoute();
        return;
      }
      try {
        postRoute();
      } catch (ZuulException e) {
        error(e);
        return;
      }
    } catch (Throwable e) {
      error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
    } finally {
      RequestContext.getCurrentContext().unset();
    }
  }

四、最后由SendResponseFilter执行返回结果,filterOrder为1000所以最好post的filter不要超过1000否则影响返回结果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 了解Java多线程的可见性与有序性

    了解Java多线程的可见性与有序性

    这篇文章主要介绍了了解Java多线程的可见性与有序性,在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。,需要的朋友可以参考下
    2019-06-06
  • ThreadPoolExecutor参数含义及源码执行流程详解

    ThreadPoolExecutor参数含义及源码执行流程详解

    这篇文章主要为大家介绍了ThreadPoolExecutor参数含义及源码执行流程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • MyBatis的各种查询功能结果接收类型的选择(推荐)

    MyBatis的各种查询功能结果接收类型的选择(推荐)

    文章介绍了MyBatis中查询结果的不同接收方式,包括单条数据和多条数据的处理方法,以及MyBatis的默认类型别名,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Java使用Collections.sort()排序的方法

    Java使用Collections.sort()排序的方法

    这篇文章介绍了Java使用Collections.sort()排序的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • Java二叉树的四种遍历(递归与非递归)

    Java二叉树的四种遍历(递归与非递归)

    这篇文章小编给大家分享的是Java二叉树的四种遍历,主要是递归与非递归,下面文章加u来详细介绍,感兴趣的小伙伴一起来学习吧
    2021-10-10
  • Springboot获取jar包中resources资源目录下的文件

    Springboot获取jar包中resources资源目录下的文件

    今天在项目中遇到一个业务场景,需要用到resources资源目录下的文件,本文主要介绍了Springboot获取jar包中resources资源目录下的文件,感兴趣的可以了解一下
    2023-12-12
  • Java中HTTP接口请求重试的实现方式

    Java中HTTP接口请求重试的实现方式

    HTTP接口请求重试是指在请求失败时,再次发起请求的机制,在实际应用中,由于网络波动、服务器故障等原因,HTTP接口请求可能会失败,为了保证系统的可用性和稳定性,需要对HTTP接口请求进行重试,所以本文给大家介绍了HTTP接口请求重试的实现方式,需要的朋友可以参考下
    2024-01-01
  • Java.lang.NullPointerException的错误解决

    Java.lang.NullPointerException的错误解决

    Java中NullPointerException是一种常见的运行时异常,通常发生在尝试调用null对象的方法或访问其属性时,具有一定的参考价值,感兴趣的可以了解一下
    2024-09-09
  • Java消息队列的简单实现代码

    Java消息队列的简单实现代码

    本篇文章主要介绍了Java消息队列的简单实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • SpringBoot启动应用及回调监听原理解析

    SpringBoot启动应用及回调监听原理解析

    这篇文章主要介绍了SpringBoot启动应用及回调监听原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论