文档章节

SpringCloud之zuul源码解析

魔法王者安琪拉
 魔法王者安琪拉
发布于 02/11 14:10
字数 638
阅读 464
收藏 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否则影响返回结果

© 著作权归作者所有

共有 人打赏支持
魔法王者安琪拉
粉丝 79
博文 96
码字总数 32078
作品 0
深圳
程序员
springcloud 客户端负载均衡 ribbon

------------------------------------------------------------------------------------------------------------ springcloud (零) springboot 基础 下载 springcloud (一)服务注册中心 ......

curiousby
2017/02/09
0
0
springcloud eureka 服务注册中心

------------------------------------------------------------------------------------------------------------ springcloud (零) springboot 基础 下载 springcloud (一)服务注册中心 ......

curiousby
2017/02/08
0
0
springcloud 服务网关 gateway zuul

------------------------------------------------------------------------------------------------------------ springcloud (零) springboot 基础 下载 springcloud (一)服务注册中心 ......

curiousby
2017/02/17
0
0
史上最简单的 SpringCloud 教程

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

外星人et59
04/21
0
0
springcloud 断路由hystrix

------------------------------------------------------------------------------------------------------------ springcloud (零) springboot 基础 下载 springcloud (一)服务注册中心 ......

curiousby
2017/02/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spark Load Data and Export Data

Load_Data_Command 一、导入数据-加载csv文件数据作为spark 临时表DataSource(不需要提前创建表,方便数据分析) 该命令将csv文件导入到临时表中,命令格式为 load data '文件路径' table [...

Avner
14分钟前
1
0
CDH5.13离线安装Spark2.3详细步骤

简介: 在我的CDH5.13集群中,默认安装的spark是1.6版本,这里需要将其升级为spark2.x版本。经查阅官方文档,发现spark1.6和2.x是可以并行安装的,也就是说可以不用删除默认的1.6版本,可以直...

hblt-j
17分钟前
1
0
Add XSS protection headers on Nginx

Add XSS protection headers on Nginx Add the following line in the http or server part of your Nginx configuration : ... # XSS Protection add_header X-Frame-Opt......

idoz
18分钟前
1
0
cmake windows 配置xp toolset

MPRO
24分钟前
1
0
day125-20181023-英语流利阅读-待学习

外卖员不要哭,打零工不容易 雪梨 2018-10-23 1.今日导读 上期我们讲到,有人认为:“零工经济”虽然没有占领全世界,但它剥夺了劳动者的合法权利,加剧了工作的不稳定性,那么“零工经济”是...

飞鱼说编程
36分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部