在这里我们讨论下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客户端的非延迟创建是在应用程序启动后才立即执行,所以依然生效。
网友评论