Spring Cloud Ribbon 全解 (8)
阿新 • • 發佈:2019-02-07
一般SpringCloud環境下是Ribbon+Eureka一起使用的:
SpringCloud環境下Ribbon+Eureka配置
示例專案
新增依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId >
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId >
<artifactId>spring-retry</artifactId>
</dependency>
新增配置:
spring.application.name=Scanfold-SpringCloud-RibbonWithEureka
server.port=8081
######## ribbon ########
#ribbon連線超時
test-service-provider.ribbon.ConnectTimeout=50
#ribbon讀超時
test-service-provider.ribbon.ReadTimeout =8000
#最多重試多少臺伺服器
test-service-provider.ribbon.MaxAutoRetriesNextServer=1
#每臺伺服器最多重試次數,但是首次呼叫不包括在內
test-service-provider.ribbon.MaxAutoRetries=1
test-service-provider.ribbon.retryableStatusCodes=500
test-service-provider.ribbon.OkToRetryOnAllOperations=true
#服務過期時間配置,超過這個時間沒有接收到心跳EurekaServer就會將這個例項剔除
#注意,EurekaServer一定要設定eureka.server.eviction-interval-timer-in-ms否則這個配置無效,這個配置一般為服務重新整理時間配置的三倍
#預設90s
eureka.instance.lease-expiration-duration-in-seconds=15
#服務重新整理時間配置,每隔這個時間會主動心跳一次
#預設30s
eureka.instance.lease-renewal-interval-in-seconds=5
#eureka client重新整理本地快取時間
#預設30s
eureka.client.registryFetchIntervalSeconds=5
#eureka客戶端ribbon重新整理時間
#預設30s
ribbon.ServerListRefreshInterval=1000
eureka.instance.preferIpAddress=true
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8211/eureka/
原始碼分析
類似於純Ribbon的初始化,也是通過Intereceptor初始化Configuration,只不過這次主角是EurekaRibbonClientConfiguration:
@Bean
@ConditionalOnMissingBean
public IPing ribbonPing(IClientConfig config) {
if (this.propertiesFactory.isSet(IPing.class, this.serviceId)) {
return (IPing)this.propertiesFactory.get(IPing.class, config, this.serviceId);
} else {
NIWSDiscoveryPing ping = new NIWSDiscoveryPing();
ping.initWithNiwsConfig(config);
return ping;
}
}
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config, Provider<EurekaClient> eurekaClientProvider) {
if (this.propertiesFactory.isSet(ServerList.class, this.serviceId)) {
return (ServerList)this.propertiesFactory.get(ServerList.class, config, this.serviceId);
} else {
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(config, eurekaClientProvider);
DomainExtractingServerList serverList = new DomainExtractingServerList(discoveryServerList, config, this.approximateZoneFromHostname);
return serverList;
}
}
@Bean
public ServerIntrospector serverIntrospector() {
return new EurekaServerIntrospector();
}
@PostConstruct
public void preprocess() {
String zone = ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);
if (this.clientConfig != null && StringUtils.isEmpty(zone)) {
String availabilityZone;
if (this.approximateZoneFromHostname && this.eurekaConfig != null) {
availabilityZone = ZoneUtils.extractApproximateZone(this.eurekaConfig.getHostName(false));
log.debug("Setting Zone To " + availabilityZone);
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, availabilityZone);
} else {
availabilityZone = this.eurekaConfig == null ? null : (String)this.eurekaConfig.getMetadataMap().get("zone");
if (availabilityZone == null) {
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig.getRegion());
availabilityZone = zones != null && zones.length > 0 ? zones[0] : null;
}
if (availabilityZone != null) {
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone, availabilityZone);
}
}
}
RibbonUtils.setRibbonProperty(this.serviceId, CommonClientConfigKey.DeploymentContextBasedVipAddresses.key(), this.serviceId);
RibbonUtils.setRibbonProperty(this.serviceId, CommonClientConfigKey.EnableZoneAffinity.key(), "true");
}
通過原始碼,可以看出,IPing的預設實現變成了NIWSDiscoveryPing,ServerList的預設實現變成DomainExtractingServerList;
NIWSDiscoveryPing之前的文章裡面我們分析過其原始碼,ServerList的預設實現是基於DiscoveryEnabledNIWSServerList(之前也分析過)外面再包一層DomainExtractingServerList
這個DomainExtractingServerList其實就是在DiscoveryEnabledNIWSServerList返回的Server基礎上封裝了Zone資訊,主要獲取和更新邏輯還是DiscoveryEnabledNIWSServerList
至於呼叫還有重試和之前純Ribbon的邏輯是一樣的,這裡不再贅述