Spring cloud Gateway 源码(一) 基本组件

    官网doc地址:Spring Cloud GatewayLevel up your Java code and explore what Spring can do for you.https://spring.io/projects/spring-cloud-gateway#learn

    本文使用 springcloud 版本为: 2020.0.5

    本文只记录我读源码的过程。案例demo和某些名词可以到官网翻阅。

目录

1、配置文件

 

2、GatewayAutoConfiguration

2.1 Init Befor and After

2.1.1 AutoConfigureBefore

2.1.2 AutoConfigureAfter

2.2 GatewayProperties

2.3 RouteDefinitionLocator

2.4 RouteLocator

2.5  RouteRefreshListener

2.6 FilteringWebHandler

2.7  RoutePredicateHandlerMapping

2.8 其他


1、配置文件

        spring gateway的初始化配置文件 spring.factories 在 spring-cloud-gateway-server的META-INF下。

    

         根据springboot基础知识,我们知道当我们集成引用gateway后,会进行AutoConfiguration的加载。那么当有这么多configuration的时候,根据经验,我们先看以项目名命名的GatewayAutoConfiguration。

 

2、GatewayAutoConfiguration

2.1 Init Befor and After

2.1.1 AutoConfigureBefore

        我们看到在gatewayAutoConfiguration的类上有一些注解,我们只看和初始化相关的

@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayReactiveLoadBalancerClientAutoConfiguration.class,
		GatewayClassPathWarningAutoConfiguration.class })

        Before就是指定当前类的加载需要在这两个类之前,虽然我们不知道这两个类具体是坐什么的,但是我们根据这两个类的包或者名字可以看出来是 WebFlux和Reactive相关的,这个要涉及到这块的一些基础知识,我只知道他是响应式编程,是和springMvc差不多的架构,而根据里面的配置其实就是初始化一些WebFlux框架相关的组件。例如一些HttpHandler,RequestMappingHandler等,这块我也不是很懂,就不误人子弟了。

2.1.2 AutoConfigureAfter

  •  GatewayClassPathWarningAutoConfiguration

       

         这个类其实就是检查gateway所需要的组件环境的,gateway是基于webflux开发的,所以我们的环境内不能包含springmvc的东西。所以如果在项目中的某些依赖暗含了对spring-boot-starter-web的依赖,是需要排除依赖关系的。

  •    GatewayReactiveLoadBalancerClientAutoConfiguration

   

        从名字就可以看出来这个是做负载均衡配置的,他After了 spring cloud的loadbalancer配置。而里面的两个初始化bean从名字看都是filter,都实现了GlobalFilter接口。而根据官网对此的解释如下:Spring Cloud Gateway

        The GlobalFilter interface has the same signature as GatewayFilter. These are special filters that are conditionally applied to all routes.

            可以看到这是一个全局过滤器。而且和Gateway的filter可以组合起来用 order来决定执行顺序。从ReactiveLoadBalancerClientFilter内的filter执行逻辑来看,我先猜测他就是做负载均衡转换的,会转换lb开头的服务名到目前服务。

        

2.2 GatewayProperties

        是解析我们在项目中配置文件定义的gateway配置的解析文件。当我们不知道都支持哪些配置或者配置支持哪些类型时,可以翻阅这个类来查看参考。比如 router路由配置,里面定义的是RouteDefinition,我们学过spring,根据Definition这个后缀就可以知道,这个和BeanDefinition原理是一样的,spring将配置解析到这个类里,然后由这个类做一些加工检查等最后生成相应的路由bean。其他的例如 FilterDefinition等原理一致。

下面看一些在autoConfiguration种初始化的主要bean。

2.3 RouteDefinitionLocator

        我们刚刚说了RouteDefinition,而这个Locator我们可以点进去查看这个类的方法,只存在一个方法,就是获取 RouteDefinitions,所以我猜测它就是一个加工RouteDefinition并获取列表的服务类。

        

        它的参数是一个同类型的列表,而这个类型我们可以根据IDEA工具查看它有哪些子类,可以按这些子类在查下,我们看到它的这些子类也大部分会被执行初始化bean的方法。例如:DiscoveryClientRouteDefinitionLocator是在GatewayDiscoveryClientAutoConfiguration内,InMemoryRouteDefinitionRepository就是在本gatewayAutoConfiguration中。

        而返回值CompositeRouteDefinitionLocator,我们点进去看它的构造方法,可以看到它其实就是把构造参数集合内的属性都整合在一起,委派了内部的一个属性,并在接口方法getRouteDefinitions时进行了统一处理并返回。

2.4 RouteLocator

        

        和上面方法一样,我们可以从名字以及查看返回值类内方法来判断,它是一个支持RouteDefinition转换成 Route的类。RouteDefinitionRouteLocator这个是它的实现类,可以看它的

getRoutes方法,它会将谓词,过滤器等Definition都转换成对应的目标类并设置进route的属性。

2.5  RouteRefreshListener

     

     从名字上来看,这就是路由刷新的监听程序,ConditionalOnClass规定只有当我们引用了springcloud 的discovery服务发现时候才会进行初始化这个bean。listener会注册监听程序,监听ApplicationEvent,当有event进来会发布RefreshRoutesEvent,会有相应的监听程序来监听这个event并且执行相应的刷新操作。这个等后续写动态路由再写。

2.6 FilteringWebHandler

 这个是核心的web处理类,它最终会糅合GlobalFilter和GatewayFilter组成过滤器链并排序后执行各过滤器逻辑。后续记录整体执行流程时就知道了。

   构造方法:

public FilteringWebHandler(List<GlobalFilter> globalFilters) {
		this.globalFilters = loadFilters(globalFilters);
	}

	private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
		return filters.stream().map(filter -> {
            //将globalFilter使用gatewayFilter适配器进行适配
			GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
            //当是order子类时,使用order相关适配器适配返回,保证排序
			if (filter instanceof Ordered) {
				int order = ((Ordered) filter).getOrder();
				return new OrderedGatewayFilter(gatewayFilter, order);
			}
			return gatewayFilter;
		}).collect(Collectors.toList());
	}

2.7  RoutePredicateHandlerMapping

        这个类是当有请求进来后,会使用这个handlerMapping查找请求地址匹配哪些路由

        

2.8 其他

        其他还有很多需要初始化的Bean,这些对象都是处理路由的具体Filter和Predicate,比如 处理AddRequestHeader的addRequestHeaderGatewayFilterFactory()方法,它对应的就是配置文件中:- AddRequestHeader=X-Request-red, blue 这部分。

        而这些GatewayFilterFactory都最终实现了 GatewayFilterFactory类。那么这些factory是在哪里应用的呢?还记得我们之前的 RouteDefinitionRouteLocator 么,这个是构造最终路由的实现类。我们看到它的构造方法里有一个参数,是List<GatewayFilterFactory>,我们可以debug看看

        

        正是我们想要查找的各种factory,这个类内有个属性gatewayFilterFactories,我们看代码它是将参数内的factory放到了这个属性内,它是一个HashMap,key就是factory的name,这个name就等于我们在application.yml中做的配置的key,例如AddRequestHeaderGatewayFilterFactory,它的name就是AddRequestHeader。这样我们就可以用routeDefinition中初始化的filter属性的key来寻找它应该由哪个filterFactory进行构造filter进行处理。

//参数id就是route配置的id,list<filterDefinition> 就是我们配置在route内的filter集合
List<GatewayFilter> loadGatewayFilters(String id, List<FilterDefinition> filterDefinitions) {
        
		ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
        
		for (int i = 0; i < filterDefinitions.size(); i++) {
			FilterDefinition definition = filterDefinitions.get(i);
            //我们上面说了,factory的name就是我们配置的key,不然也对应不上
			GatewayFilterFactory factory = this.gatewayFilterFactories.get(definition.getName());
			if (factory == null) {
				throw new IllegalArgumentException(
						"Unable to find GatewayFilterFactory with name " + definition.getName());
			}
			if (logger.isDebugEnabled()) {
				logger.debug("RouteDefinition " + id + " applying filter " + definition.getArgs() + " to "
						+ definition.getName());
			}

			// @formatter:off
			Object configuration = this.configurationService.with(factory)
					.name(definition.getName())
					.properties(definition.getArgs())
					.eventFunction((bound, properties) -> new FilterArgsEvent(
							// TODO: why explicit cast needed or java compile fails
							RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
					.bind();
			// @formatter:on

			// some filters require routeId
			// TODO: is there a better place to apply this?
			if (configuration instanceof HasRouteId) {
				HasRouteId hasRouteId = (HasRouteId) configuration;
				hasRouteId.setRouteId(id);
			}
            //这里转换成gatewayfilter并加入到排序集合内
			GatewayFilter gatewayFilter = factory.apply(configuration);
			if (gatewayFilter instanceof Ordered) {
				ordered.add(gatewayFilter);
			}
			else {
				ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
			}
		}

		return ordered;
	}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值