欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈SpringCloud之zuul源码解析

程序员文章站 2022-05-03 10:30:19
zuul各版本实现存在一些微小的变化,总的实现思想未改变,以spring-cloud-netflix-core-1.3.6.release为例 一、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否则影响返回结果

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