美文网首页
SpringCloud解析九:Consul与Ribbon集成原理

SpringCloud解析九:Consul与Ribbon集成原理

作者: 一根线条 | 来源:发表于2020-02-20 18:18 被阅读0次

    在这里我们讨论下Consul与Ribbon的集成过程,以spring-cloud-consul-discovery-2.2.0.RELEASE.jar为例。在该包的/META-INF/spring.factories中包含了如下的内容

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration,\
    org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerAutoConfiguration,\
    org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration,\
    org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration,\
    org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration,\
    org.springframework.cloud.consul.discovery.reactive.ConsulReactiveDiscoveryClientConfiguration,\
    org.springframework.cloud.consul.discovery.ConsulCatalogWatchAutoConfiguration, \
    org.springframework.cloud.consul.support.ConsulHeartbeatAutoConfiguration
    org.springframework.cloud.bootstrap.BootstrapConfiguration=\
    org.springframework.cloud.consul.discovery.configclient.ConsulDiscoveryClientConfigServiceBootstrapConfiguration
    

    这里的RibbonConsulAutoConfiguration便是入口。该配置类定义如下:

    @Configuration(proxyBeanMethods = false)
    @EnableConfigurationProperties
    @ConditionalOnConsulEnabled
    @ConditionalOnBean(SpringClientFactory.class)
    @ConditionalOnProperty(value = "spring.cloud.consul.ribbon.enabled",
            matchIfMissing = true)
    @AutoConfigureAfter(RibbonAutoConfiguration.class)
    @RibbonClients(defaultConfiguration = ConsulRibbonClientConfiguration.class)
    public class RibbonConsulAutoConfiguration {
    
    }
    

    从上代码可得到以下信息
    1)该配置类在RibbonAutoConfiguration之后执行
    2)修改Ribbon的默认配置为ConsulRibbonClientConfiguration

    接着把目光转向ConsulRibbonClientConfiguration,该类定义如下:

    @Configuration(proxyBeanMethods = false)
    public class ConsulRibbonClientConfiguration {
    
        protected static final String VALUE_NOT_SET = "__not__set__";
    
        protected static final String DEFAULT_NAMESPACE = "ribbon";
    
        @Autowired
        private ConsulClient client;
    
        @Value("${ribbon.client.name}")
        private String serviceId = "client";
    
        public ConsulRibbonClientConfiguration() {
        }
    
        public ConsulRibbonClientConfiguration(String serviceId) {
            this.serviceId = serviceId;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public ServerList<?> ribbonServerList(IClientConfig config,
                ConsulDiscoveryProperties properties) {
            ConsulServerList serverList = new ConsulServerList(this.client, properties);
            serverList.initWithNiwsConfig(config);
            return serverList;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public ServerListFilter<Server> ribbonServerListFilter() {
            return new HealthServiceServerListFilter();
        }
    
        @Bean
        @ConditionalOnMissingBean
        public IPing ribbonPing() {
            return new ConsulPing();
        }
    
        @Bean
        @ConditionalOnMissingBean
        public ConsulServerIntrospector serverIntrospector() {
            return new ConsulServerIntrospector();
        }
    
        @PostConstruct
        public void preprocess() {
            setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
            setProp(this.serviceId, EnableZoneAffinity.key(), "true");
        }
    
        protected void setProp(String serviceId, String suffix, String value) {
            // how to set the namespace properly?
            String key = getKey(serviceId, suffix);
            DynamicStringProperty property = getProperty(key);
            if (property.get().equals(VALUE_NOT_SET)) {
                ConfigurationManager.getConfigInstance().setProperty(key, value);
            }
        }
    
        protected DynamicStringProperty getProperty(String key) {
            return DynamicPropertyFactory.getInstance().getStringProperty(key, VALUE_NOT_SET);
        }
    
        protected String getKey(String serviceId, String suffix) {
            return serviceId + "." + DEFAULT_NAMESPACE + "." + suffix;
        }
    
    }
    

    在这个类里面重写了Ribbon默认配置里面的ServerList、ServerListFilter、IPing 和ConsulServerIntrospector 。 在以前章节的分析中我们知道,Ribbon的客户端是在第一次调用的时候被创建,也就是在这里重写的这些默认配置会在第一次调用的时候被使用,从而将Consul的发现机制应用到了Ribbon中。

    注意:在Ribbon我们还可以配置将指定的服务非延迟创建,对于配置了非延迟创建的Ribbon客户端是否还能生效呢?因为Ribbon客户端的非延迟创建是在应用程序启动后才立即执行,所以依然生效。

    相关文章

      网友评论

          本文标题:SpringCloud解析九:Consul与Ribbon集成原理

          本文链接:https://www.haomeiwen.com/subject/wyezfhtx.html