Spring Cloud Ribbon 全解 (8) - SpringCloud环境下Ribbon+Eureka配置

2021-04-12 15:05:36 浏览数 (1)

本文基于SpringCloud-Dalston.SR5

一般SpringCloud环境下是Ribbon Eureka一起使用的:

SpringCloud环境下Ribbon Eureka配置

示例项目

实例项目地址:https://github.com/HashZhang/ScanfoldAll/tree/master/Scanfold-SpringCloud/Scanfold-SpringCloud-Ribbon/Scanfold-SpringCloud-RibbonWithEureka

添加依赖:

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-ribbonartifactId>
dependency>
<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-eurekaartifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>org.springframework.retrygroupId>
    <artifactId>spring-retryartifactId>
dependency>

添加配置:

代码语言:javascript复制
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:

代码语言:javascript复制
@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 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的逻辑是一样的,这里不再赘述

0 人点赞