Nacos源码学习系列第11篇服务是如何订阅的

服务订阅在服务被调用时触发,是客户端负载均衡逻辑的一部分

目录

服务请求流程图

核心类讲解

NacosRibbonClientConfiguration 

 NacosServerList 

负载均衡是怎么更新服务列表的



服务请求流程图

通过请求流程图我们发现, 在创建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方法也是唯一被负载均衡调用的接口。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值