Spring cloud gateway源码(三) 注册中心服务自动路由

        我们开始查看gateway-server种的spring.factories时,除了主要的GatewayAutoConfiguration时,还有很多其他的自动配置类,这次只看 GatewayDiscoveryClientAutoConfiguration它是做什么的,我最开始是以为它是做动态路由,结果在后续查看启动日志以及其他代码后又翻回来看发现不是。

1、自动注册服务路由

        通过查询官网文档,发现下面的解释

        

12.4. The DiscoveryClient Route Definition Locator

You can configure the gateway to create routes based on services registered with a DiscoveryClient compatible service registry.

To enable this, set spring.cloud.gateway.discovery.locator.enabled=true and make sure a DiscoveryClient implementation (such as Netflix Eureka, Consul, or Zookeeper) is on the classpath and enabled.

         可以看到这里的配置正好和GatewayDiscoveryClientAutoConfiguration中的配置对应

@Configuration(proxyBeanMethods = false)
	@ConditionalOnProperty(value = "spring.cloud.discovery.reactive.enabled", matchIfMissing = true)
	public static class ReactiveDiscoveryClientRouteDefinitionLocatorConfiguration {


		@Bean
		@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
		public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
				ReactiveDiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
			return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
		}

	}

    在往下翻官网文档就大概明白是什么意思了。我们在我们的demo 配置文件中把开关spring.cloud.gateway.discovery.locator.enabled打开。然后访问gateway的路由列表发现我们的路由列表里多了一个之前不存在的路由

        而这个test正是我为了测试路由转发的一个测试项目,并且它也是和gateway处于同一个注册中心的 。结合官网解释并本地测试就可以验证,GatewayDiscoveryClientAutoConfiguration的作用就是将中心中心的项目自动注册成路由,Predicate和filter是默认的生成规则

        

public static List<PredicateDefinition> initPredicates() {
		ArrayList<PredicateDefinition> definitions = new ArrayList<>();
		// TODO: add a predicate that matches the url at /serviceId?

		// add a predicate that matches the url at /serviceId/**
		PredicateDefinition predicate = new PredicateDefinition();
		predicate.setName(normalizeRoutePredicateName(PathRoutePredicateFactory.class));
		predicate.addArg(PATTERN_KEY, "'/'+serviceId+'/**'");
		definitions.add(predicate);
		return definitions;
	}

	public static List<FilterDefinition> initFilters() {
		ArrayList<FilterDefinition> definitions = new ArrayList<>();

		// add a filter that removes /serviceId by default
		FilterDefinition filter = new FilterDefinition();
		filter.setName(normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class));
		String regex = "'/' + serviceId + '/?(?<remaining>.*)'";
		String replacement = "'/${remaining}'";
		filter.addArg(REGEXP_KEY, regex);
		filter.addArg(REPLACEMENT_KEY, replacement);
		definitions.add(filter);

		return definitions;
	}

	@Bean
	public DiscoveryLocatorProperties discoveryLocatorProperties() {
		DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties();
		properties.setPredicates(initPredicates());
		properties.setFilters(initFilters());
		return properties;
	}

        其实它就是转换成

 predicates:
      - Path=/{serviceId}/**

         当然,如果我们想用自动注册路由又想定制其他谓词和过滤器,也是支持的

spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: CircuitBreaker
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/?(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"

   

2、服务从何而来

        从上面的代码我们可以看到,除了new一个默认的properties bean外,其实没有看到服务是怎么注册到gateway来的。我们在自动配置文件中看到new了一个DiscoveryClientRouteDefinitionLocator,根据gateway里的命名规律,我们知道它就是服务发现客户端路由转换类,我们debug看下new的参数

        这里服务发现客户端就是nacos的,也就是在nacos加载完成后,才会进行加载这个DiscoveryClientRouteDefinitionLocator  bean,此时nacos已经知道了已经有哪些服务注册在它本身了。所以在DiscoveryClientRouteDefinitionLocator构造方法中其实已经将服务列表设置进了它的属性serviceInstances里。

        我们看到DiscoveryClientRouteDefinitionLocator它本身也属于RouteDefinitionLocator,根据前面说的gateway的加载规则,在初始化RouteDefinitionRouteLocator时,会调用到DiscoveryClientRouteDefinitionLocator的getRouteDefinitions方法,在这里就进行了注册中心服务列表和配置文件规则组织成 路由定义。

        

 

 


版权声明:本文为qGANG原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。