服务订阅在服务被调用时触发,是客户端负载均衡逻辑的一部分
目录
NacosRibbonClientConfiguration
服务请求流程图
通过请求流程图我们发现, 在创建serviceId的上下文时,加载了类RibbonNacosAutoConfiguration 该类又会触发 NacosRibbonClientConfiguration类的加载
核心类讲解
NacosRibbonClientConfiguration
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config, NacosDiscoveryProperties
nacosDiscoveryProperties) {
NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties);
serverList.initWithNiwsConfig(config);
return serverList;
}
NacosRibbonClientConfiguration 会自动创建NacosServerList bean
IClientConfig 可以理解成包含调用方基本信息的配置对象 这是spring cloud中的类。
NacosServerList
//该类负责加载serverId 下的实例列表
public class NacosServerList extends AbstractServerList<NacosServer> {
private NacosDiscoveryProperties discoveryProperties;
private String serviceId;
public NacosServerList(NacosDiscoveryProperties discoveryProperties) {
this.discoveryProperties = discoveryProperties;
}
//查询服务列表[暂时没发现有地方用到]
@Override
public List<NacosServer> getInitialListOfServers() {
return getServers();
}
//查询服务列表
@Override
public List<NacosServer> getUpdatedListOfServers() {
return getServers();
}
//调用NacosNamingService查询服务实例列表
private List<NacosServer> getServers() {
try {
List<Instance> instances = discoveryProperties.namingServiceInstance()
.selectInstances(serviceId, true);
//把Instantce 包装成loadbalancer 能识别的Server对象
return instancesToServerList(instances);
}
....
}
//把Instantce 包装成loadbalancer 能识别的Server对象
private List<NacosServer> instancesToServerList(List<Instance> instances) {
List<NacosServer> result = new ArrayList<>();
...
for (Instance instance : instances) {
result.add(new NacosServer(instance));
}
return result;
}
public String getServiceId() {
return serviceId;
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
//从clientConfig 中获取当前服务的id
this.serviceId = iClientConfig.getClientName();
}
}
public class NacosServer extends Server {
private final MetaInfo metaInfo;
private final Instance instance;
private final Map<String, String> metadata;
public NacosServer(final Instance instance) {
//调用Server类的构造方法初始化server 的 IP 端口 isAlive 状态
super(instance.getIp(), instance.getPort());
this.instance = instance;
//提供server 提供服务的元数据信息
this.metaInfo = new MetaInfo() {
@Override
public String getAppName() {
return instance.getServiceName();
}
@Override
public String getServerGroup() {
return null;
}
@Override
public String getServiceIdForDiscovery() {
return null;
}
@Override
public String getInstanceId() {
return instance.getInstanceId();
}
};
this.metadata = instance.getMetadata();
}
@Override
public MetaInfo getMetaInfo() {
return metaInfo;
}
public Instance getInstance() {
return instance;
}
public Map<String, String> getMetadata() {
return metadata;
}
}
负载均衡是怎么更新服务列表的
负载均衡器ZoneAwareLoadBalancer 在初始化时
调用了父类DynamicServerListLoadBalancer的 serverListUpdater.start(updateAction)方法
该方法30秒执行一次NacosServerList.getUpdatedListOfServer方法()
public class DynamicServerListLoadBalancer {
...
//构造负载据衡器
public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing
ping,ServerList<T> serverList, ServerListFilter<T> filter,
ServerListUpdater serverListUpdater) {
super(clientConfig, rule, ping);
//这个就是我们上面的NacosServerList对象
this.serverListImpl = serverList;
//服务过滤器
this.filter = filter;
//服务更新器
this.serverListUpdater = serverListUpdater;
...
//其他部分初始化
restOfInit(clientConfig);
}
...
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);
}
//开始启动定时更新
public void enableAndInitLearnNewServersFeature() {
serverListUpdater.start(updateAction);
}
//30s 执行一次定时任务
@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 {
//执行更新
updateAction.doUpdate();
lastUpdated = System.currentTimeMillis();
}
...
}
};
scheduledFuture = getRefreshExecutor().scheduleWithFixedDelay(
wrapperRunnable,
initialDelayMs, // 默认 1s
refreshIntervalMs,// 默认 30s
TimeUnit.MILLISECONDS
);
}
...
}
//服务列表更新操作
protected final ServerListUpdater.UpdateAction updateAction = new S
erverListUpdater.UpdateAction() {
@Override
public void doUpdate() {
updateListOfServers();
}
};
}
总结
实际上nacos接入服务发现的核心类是NacosServerList. 通过自动化配置的形式注入, 其提供的getUpdatedListOfServers方法也是唯一被负载均衡调用的接口。