文档章节

SpringCloud之zuul源码解析

魔法王者安琪拉
 魔法王者安琪拉
发布于 02/11 14:10
字数 638
阅读 393
收藏 6

                                              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否则影响返回结果

© 著作权归作者所有

共有 人打赏支持
魔法王者安琪拉
粉丝 80
博文 93
码字总数 31299
作品 0
深圳
程序员
史上最简单的 SpringCloud 教程

《史上最简单的 SpringCloud 教程》系列: 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现(Eureka) 史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon) 史上最...

外星人et59
04/21
0
0
【Spring Cloud】分布式必学springcloud(一)——简介和看法

一、前言 开篇之前,我想说,springcloud会完胜dubbo。 小编以前做分布式是用的webservice、dubbo。最近的项目中,开始使用了springcloud,springcloud包含了很多的组件,这些组件是dubbo没有...

kisscatforever
04/16
0
0
SpringCloud之网关 Zuul(四)

一 Zuul简介 zuul 是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用。 Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix ...

07/17
0
0
Spring Cloud-honghu Cloud分布式微服务云系统

简介 鸿鹄云Cloud是基于SpringCloud来封装的,是一系列框架的有序集合。利用Spring Boot的开发模式简化了分布式系统基础设施的开发,如服务发现、注册、配置中心、消息总线、负载均衡、断路器...

itcloud
04/25
0
0
Springcloud应用在阿里云Kubernetes上的IP互通实践

问题 在应用微服务化方案中,Springcloud是比较常见的选择,毕竟其对于Java 的程序员来说比较友好,基于Springboot的编程方式也使得门槛比较低。但是在将Springcloud的应用运行到Kubernetes容...

了哥-duff
06/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

数据新增--》id和name到对象----》dom渲染

<html> <head> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="http://www.reoonet.com/plu......

柴高八斗之父
4分钟前
0
0
使用Nexus Repository 3的十二个理由

使用Nexus Repository 3的十二个理由 2017年03月14日 20:20:43 阅读数:13383 随着Nexus Repository Manager OSS 3的发布(目前更新至3.2.1),虽然目前还是Nexus 2和Nexus 3并行的状态,但是...

linjin200
6分钟前
0
0
【转】分布式锁实现(二):Zookeeper

设计实现 一、基本算法 1.在某父节点下创建临时有序节点2.判断创建的节点是否是当前父节点下所有子节点中序号最小的3.是序号最小的成功获取锁,否则监听比自己小的那个节点,进行watch,...

talen
16分钟前
0
0
dkhadoop大数据智能分析平台监控参数说明

2018年国内大数据公司50强榜单排名已经公布了出来,大快以黑马之姿闯入50强,并摘得多项桂冠。Hanlp自然语言处理技术也荣膺了“2018中国数据星技术”奖。对这份榜单感兴趣的可以找一下看看。...

左手的倒影
22分钟前
0
0
Java 读写锁实现原理

最近做的一个小项目中有这样的需求:整个项目有一份config.json保存着项目的一些配置,是存储在本地文件的一个资源,并且应用中存在读写(读>>写)更新问题。既然读写并发操作,那么就涉及到...

编辑部的故事
24分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部