nacos源码学习--服务注册与发现

基于源码版本(nacos1.4.2)

Nacos的注册: 

  注册功能: 客户端启动 找到Nacos服务端 首先进到方法  serverProxy.registerService(groupedServiceName, groupName, instance);

        其发送了一个Http请求向服务端 用以注册Instance

        服务端: 接受客户端请求后  初始化相关命名空间等信息 addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);

          这些信息先会放入一个Set<Instance>中 真正的注册是如何进行的呢,通过一个SchedulerTask线程池定时任务,然后将信息放入注册表

--------------put-------------

public void putService(Service service) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
synchronized (putServiceLock) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
serviceMap.put(service.getNamespaceId(), new ConcurrentSkipListMap<>());
}
}
}
serviceMap.get(service.getNamespaceId()).putIfAbsent(service.getName(), service);
}
---------- 线程池初始化-------------
@PostConstruct
public void init() {
GlobalExecutor.submitDistroNotifyTask(notifier);
}

 ------------notifyer的run方法 死循环 不断读客户端向队列注册的信息 然后实现异步注册--------------

@Override
public void run() {
Loggers.DISTRO.info("distro notifier started");

for (; ; ) {
try {
Pair<String, DataOperation> pair = tasks.take();
handle(pair);
} catch (Throwable e) {
Loggers.DISTRO.error("[NACOS-DISTRO] Error while handling notifying task", e);
}
}
}

 ------------------------

  发现功能: 客户端会调用方法 public ServiceInfo getServiceInfo(final String serviceName, final String clusters) 

// @ZyxNote服务注册与发现 从一个Map里面拿
ServiceInfo serviceObj = getServiceInfo0(serviceName, clusters);

// @ZyxNote服务注册与发现 服务注册 第一次来 肯定是空 进入下列if体中
if (null == serviceObj) {
serviceObj = new ServiceInfo(serviceName, clusters);

serviceInfoMap.put(serviceObj.getKey(), serviceObj);

updatingMap.put(serviceName, new Object());
// @ZyxNote服务注册与发现 更新服务列表方法
updateServiceNow(serviceName, clusters);
updatingMap.remove(serviceName);

} else if (updatingMap.containsKey(serviceName)) {

if (UPDATE_HOLD_INTERVAL > 0) {
// hold a moment waiting for update finish
synchronized (serviceObj) {
try {
serviceObj.wait(UPDATE_HOLD_INTERVAL);
} catch (InterruptedException e) {
NAMING_LOGGER
.error("[getServiceInfo] serviceName:" + serviceName + ", clusters:" + clusters, e);
}
}
}
}

// @ZyxNote服务注册与发现 定时任务
scheduleUpdateIfAbsent(serviceName, clusters);

-------------这个定时任务做了什么呢?---------------

 public void scheduleUpdateIfAbsent(String serviceName, String clusters) {

    if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
return;
}

synchronized (futureMap) {
if (futureMap.get(ServiceInfo.getKey(serviceName, clusters)) != null) {
return;
}

// @ZyxNote服务注册与发现 进到这里面
ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, clusters));
futureMap.put(ServiceInfo.getKey(serviceName, clusters), future);
}
}
--------------追进去UpdateTask看-------------
@Override
public void run() {
long delayTime = DEFAULT_DELAY;

try {
ServiceInfo serviceObj = serviceInfoMap.get(ServiceInfo.getKey(serviceName, clusters));

// @ZyxNote服务注册与发现 又一次查询了服务列表
if (serviceObj == null) {
updateService(serviceName, clusters);
return;
}

       服务端: 客户端请求来到了InstanceController.doSrvIpxt(..)

----------------------706行------------------------

// @ZyxNote服务注册与发现 最核心方法 获取所有服务实例 追进去看看拿到了什么东西
srvedIPs = service.srvIPs(Arrays.asList(StringUtils.split(clusters, ",")));
--------------srvIPs(..)----------------
public List<Instance> srvIPs(List<String> clusters) {
if (CollectionUtils.isEmpty(clusters)) {
clusters = new ArrayList<>();
clusters.addAll(clusterMap.keySet());
}
// @ZyxNote服务注册与发现 追进去
return allIPs(clusters);
}
--------------allIPs(..)--------------------
public List<Instance> allIPs(List<String> clusters) {
List<Instance> result = new ArrayList<>();
for (String cluster : clusters) {
Cluster clusterObj = clusterMap.get(cluster);
if (clusterObj == null) {
continue;
}

// @ZyxNote服务注册与发现 追进去
result.addAll(clusterObj.allIPs());
}
return result;
}
------------allIPs()---------------
// @ZyxNote服务注册与发现 填充result的方法
public List<Instance> allIPs() {
List<Instance> allInstances = new ArrayList<>();
// @ZyxNote服务注册与发现 填充了持久化/临时 实例 即Cluster类之下的两个Set
allInstances.addAll(persistentInstances);
allInstances.addAll(ephemeralInstances);
return allInstances;
}

------------------------------------------------------------

    至此 服务端服务发现结束 客户端向服务端发起的请求 服务端会相应一个List<Instance> 装有持久化和临时实例

 

 

 

 

 

ps~~: 一些琐碎技术点 @FunctionalInterface JDK1.8新特性 函数式接口声明

posted @ 2021-09-30 17:24  却道。此心安处是吾乡  阅读(107)  评论(0编辑  收藏  举报