浅谈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实现平铺列表(List)互转树形(Tree)结构

    Java实现平铺列表(List)互转树形(Tree)结构

    本文主要介绍了Java实现平铺列表(List)互转树形(Tree)结构,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 下面通过本文给大家分享Java concurrency之CountDownLatch原理和示例,需要的的朋友参考下吧
    2017-06-06
  • 详解java中finalize的实现与相应的执行过程

    详解java中finalize的实现与相应的执行过程

    在常规的java书籍中,即会描述 object的finalize方法是用于一些特殊的对象在回收之前再做一些扫尾的工作,但是并没有说明此是如何实现的.本篇从java的角度(不涉及jvm以及c++),有需要的朋友们可以参考借鉴。
    2016-09-09
  • 浅谈java对象的比较

    浅谈java对象的比较

    这篇文章主要给大家分享java对象的比较,主要有元素的比较、类的比较及比较的方法,想具体了解的小伙伴和小编一起进入下面文章内容吧
    2021-10-10
  • Java数据结构之HashMap和HashSet

    Java数据结构之HashMap和HashSet

    这篇文章主要介绍了HashMap和HashSet,什么是哈希表以及HashMap的部分源码解读,想了解更多的小伙伴,可以参考阅读本文
    2023-03-03
  • java读取图片并显示方式

    java读取图片并显示方式

    这篇文章主要介绍了java读取图片并显示方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 如何在Spring Boot中实现异步处理与并发控制

    如何在Spring Boot中实现异步处理与并发控制

    本文我们将深入探讨如何在Spring Boot中实现异步处理与并发控制,这一过程涉及到异步任务的执行、线程池的配置、以及并发控制的实践,以帮助我们提升应用的性能和响应能力,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • 实现quartz定时器及quartz定时器原理介绍

    实现quartz定时器及quartz定时器原理介绍

    Quartz是一个大名鼎鼎的Java版开源定时调度器,功能强悍,使用方便,下面我们看看如何使用它
    2013-12-12
  • 深入分析:用1K内存实现高效I/O的RandomAccessFile类的详解

    深入分析:用1K内存实现高效I/O的RandomAccessFile类的详解

    本篇文章是对用1K内存实现高效I/O的RandomAccessFile类的详细分析介绍,需要的朋友参考下
    2013-05-05
  • 聊聊Arrays.deepToString()和Arrays.toString()的区别

    聊聊Arrays.deepToString()和Arrays.toString()的区别

    这篇文章主要介绍了聊聊Arrays.deepToString()和Arrays.toString()的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论