不懂Ribbon原理的可以进来看看哦,分析RibbonClientConfiguration完成了哪些核心初始操作

| IClientConfig | DefaultClientConfigImpl | 管理配置接口 |

| IRule | ZoneAvoidanceRule | 均衡策略接口 |

| IPing | DummyPing | 检查服务可用性接口 |

| ServerList | ConfigurationBasedServerList | 获取服务列表接口 |

| ILoadBalancer | ZoneAwareLoadBalancer | 负载均衡接口 |

| ServerListUpdater | PollingServerListUpdater | 定时更新服务列表接口 |

| ServerIntrospector | DefaultServerIntrospector | 安全端口接口 |

@Bean

@ConditionalOnMissingBean

public IClientConfig ribbonClientConfig() {

DefaultClientConfigImpl config = new DefaultClientConfigImpl();

config.loadProperties(this.name);

config.set(Com

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

monClientConfigKey.ConnectTimeout, 1000);

config.set(CommonClientConfigKey.ReadTimeout, 1000);

config.set(CommonClientConfigKey.GZipPayload, true);

return config;

}

@Bean

@ConditionalOnMissingBean

public IRule ribbonRule(IClientConfig config) {

if (this.propertiesFactory.isSet(IRule.class, this.name)) {

return (IRule)this.propertiesFactory.get(IRule.class, config, this.name);

} else {

ZoneAvoidanceRule rule = new ZoneAvoidanceRule();

rule.initWithNiwsConfig(config);

return rule;

}

}

@Bean

@ConditionalOnMissingBean

public IPing ribbonPing(IClientConfig config) {

return (IPing)(this.propertiesFactory.isSet(IPing.class, this.name) ? (IPing)this.propertiesFactory.get(IPing.class, config, this.name) : new DummyPing());

}

@Bean

@ConditionalOnMissingBean

public ServerList ribbonServerList(IClientConfig config) {

if (this.propertiesFactory.isSet(ServerList.class, this.name)) {

return (ServerList)this.propertiesFactory.get(ServerList.class, config, this.name);

} else {

ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();

serverList.initWithNiwsConfig(config);

return serverList;

}

}

@Bean

@ConditionalOnMissingBean

public ServerListUpdater ribbonServerListUpdater(IClientConfig config) {

return new PollingServerListUpdater(config);

}

@Bean

@ConditionalOnMissingBean

public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList serverList, ServerListFilter serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {

return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name) ? (ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name) : new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));

在众多的默认实现中比较重要的是【ILoadBalancer】对象的实现。即【ZoneAwareLoadBalancer】的实现。实现的原理图为:

请添加图片描述

在【ZoneAwareLoadBalancer】里面完成了服务地址动态获取和服务地址更新定时任务的配置。首先会进入【ZoneAwareLoadBalancer】的构造方法中

public ZoneAwareLoadBalancer(IClientConfig clientConfig, IRule rule,

IPing ping, ServerList serverList, ServerListFilter filter,

ServerListUpdater serverListUpdater) {

super(clientConfig, rule, ping, serverList, filter, serverListUpdater);

}

通过源码能够发现会调用父类中的构造方法。

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping,

ServerList serverList, ServerListFilter filter,

ServerListUpdater serverListUpdater) {

// 继续调用父类中的方法

super(clientConfig, rule, ping);

this.serverListImpl = serverList;

this.filter = filter;

this.serverListUpdater = serverListUpdater;

if (filter instanceof AbstractServerListFilter) {

((AbstractServerListFilter) filter).setLoadBalancerStats(getLoadBalancerStats());

}

// 完成相关的初始操作 服务地址获取和更新

restOfInit(clientConfig);

}

在上面的源码中我们先继续跟踪父类中的方法。

void initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping, LoadBalancerStats stats) {

this.config = clientConfig;

String clientName = clientConfig.getClientName();

this.name = clientName;

// 设置了定时任务的间隔时间为30秒。

int pingIntervalTime = Integer.parseInt(""

  • clientConfig.getProperty(

CommonClientConfigKey.NFLoadBalancerPingInterval,

Integer.parseInt(“30”)));

int maxTotalPingTime = Integer.parseInt(""

  • clientConfig.getProperty(

CommonClientConfigKey.NFLoadBalancerMaxTotalPingTime,

Integer.parseInt(“2”)));

setPingInterval(pingIntervalTime);

setMaxTotalPingTime(maxTotalPingTime);

// cross associate with each other

// i.e. Rule,Ping meet your container LB

// LB, these are your Ping and Rule guys …

setRule(rule);

setPing(ping);

setLoadBalancerStats(stats);

rule.setLoadBalancer(this);

if (ping instanceof AbstractLoadBalancerPing) {

((AbstractLoadBalancerPing) ping).setLoadBalancer(this);

}

logger.info(“Client: {} instantiated a LoadBalancer: {}”, name, this);

boolean enablePrimeConnections = clientConfig.get(

CommonClientConfigKey.EnablePrimeConnections, DefaultClientConfigImpl.DEFAULT_ENABLE_PRIME_CONNECTIONS);

if (enablePrimeConnections) {

this.setEnablePrimingConnections(true);

PrimeConnections primeConnections = new PrimeConnections(

this.getName(), clientConfig);

this.setPrimeConnections(primeConnections);

}

init();

}

在initWithConfig方法中比较中的就是设置了定时任务的间隔时间。然后我们再回到restOfInit方法中。

void restOfInit(IClientConfig clientConfig) {

boolean primeConnection = this.isEnablePrimingConnections();

// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()

this.setEnablePrimingConnections(false);

// 设置定时任务

enableAndInitLearnNewServersFeature();

// 获取并更新服务地址

updateListOfServers();

if (primeConnection && this.getPrimeConnections() != null) {

this.getPrimeConnections()

.primeConnections(getReachableServers());

}

this.setEnablePrimingConnections(primeConnection);

LOGGER.info(“DynamicServerListLoadBalancer for client {} initialized: {}”, clientConfig.getClientName(), this.toString());

}

先看enableAndInitLearnNewServersFeature方法

public void enableAndInitLearnNewServersFeature() {

LOGGER.info(“Using serverListUpdater {}”, serverListUpdater.getClass().getSimpleName());

serverListUpdater.start(updateAction);

}

start方法的实现有多种,根据我们的服务选择对应的选择即可。比如本地就使用PollingServerListUpdater,如果是Eureka注册中心就选择EurekaNotificationServerListUpdater.

请添加图片描述

以本地为例:

@Override

public synchronized void start(final UpdateAction updateAction) {

if (isActive.compareAndSet(false, true)) {

// 定时任务的 任务体

final Runnable wrapperRunnable = new Runnable() {

@Override

public void run() {

if (!isActive.get()) {

if (scheduledFuture != null) {

scheduledFuture.cancel(true);

}

return;

}

try {

// doUpdate()的方法体要注意

updateAction.doUpdate();

lastUpdated = System.currentTimeMillis();

} catch (Exception e) {

logger.warn(“Failed one update cycle”, e);

}

}

};

// 设置定时任务 10秒开始第一次检查,间隔时间是30秒

scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(

wrapperRunnable,

initialDelayMs,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值