Spring Cloud 2.2.2 源碼之五十五nacos服務端處理註冊實例請求三
Service模型大致結構
ServiceManager的addIpAddresses
上篇說到增加實例這裏,看看他是怎麼添加的:
ServiceManager的addIpAddresses
做的是一個添加的操作。
public static final String UPDATE_INSTANCE_ACTION_ADD = "add";
public List<Instance> addIpAddresses(Service service, boolean ephemeral, Instance... ips) throws NacosException {
return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD, ephemeral, ips);
}
updateIpAddresses更新服務實例
這裏面還做了挺多的事,先是獲取老的數據(持久的或者臨時的),從一致性服務裏獲取,因爲這個數據是要同步更新的,所以要拿出來及時更新,然後獲取服務實例(持久的或者臨時的),用他們來更新的老的數據,然後遍歷新增的實例,如果沒有集羣的話先創建集羣,並初始化集羣,會開啓心跳檢查,最後根據是添加還是刪除實例來更新老的實例映射,最後封裝成集合返回最新的實例集合。
public List<Instance> updateIpAddresses(Service service, String action, boolean ephemeral, Instance... ips) throws NacosException {
//獲取老的實例集合數據
Datum datum = consistencyService.get(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), ephemeral));
//獲取集羣中所有相關的實例集合,臨時的或者是永久的
List<Instance> currentIPs = service.allIPs(ephemeral);
Map<String, Instance> currentInstances = new HashMap<>(currentIPs.size());//IP端口和實例的映射
Set<String> currentInstanceIds = Sets.newHashSet();//實例ID集合
//放入對應的集合裏
for (Instance instance : currentIPs) {
currentInstances.put(instance.toIPAddr(), instance);
currentInstanceIds.add(instance.getInstanceId());
}
//更新後的老的實例集合
Map<String, Instance> instanceMap;
if (datum != null) {//根據當前服務實例的健康標誌和心跳時間,來更新老的實例集合數據
instanceMap = setValid(((Instances) datum.value).getInstanceList(), currentInstances);
} else {//重新創建一個
instanceMap = new HashMap<>(ips.length);
}
for (Instance instance : ips) {//遍歷新的實例
if (!service.getClusterMap().containsKey(instance.getClusterName())) {//不存在就創建服務實例集羣
Cluster cluster = new Cluster(instance.getClusterName(), service);
cluster.init();//初始化,開啓集羣心跳檢查
service.getClusterMap().put(instance.getClusterName(), cluster);//添加服務實例集羣
Loggers.SRV_LOG.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
instance.getClusterName(), instance.toJSON());
}
//刪除操作的話就刪除老的實例集合的數據
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
instanceMap.remove(instance.getDatumKey());
} else {//否則添加
instance.setInstanceId(instance.generateInstanceId(currentInstanceIds));
instanceMap.put(instance.getDatumKey(), instance);
}
}
if (instanceMap.size() <= 0 && UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD.equals(action)) {
throw new IllegalArgumentException("ip list can not be empty, service: " + service.getName() + ", ip list: "
+ JSON.toJSONString(instanceMap.values()));
}
//返回總的實例集合
return new ArrayList<>(instanceMap.values());
}
Service的allIPs獲取集羣中的實例集合
遍歷集羣,獲取集羣裏的實例集合,臨時的或者是永久的。
public List<Instance> allIPs(boolean ephemeral) {
List<Instance> allIPs = new ArrayList<>();
for (Map.Entry<String, Cluster> entry : clusterMap.entrySet()) {
allIPs.addAll(entry.getValue().allIPs(ephemeral));
}
return allIPs;
}
ServiceManager的setValid更新老的實例集合
其實就是用服務集羣中獲取的實例集合去更新老的實例集合,健康狀態和心跳時間。
private Map<String, Instance> setValid(List<Instance> oldInstances, Map<String, Instance> map) {
Map<String, Instance> instanceMap = new HashMap<>(oldInstances.size());
for (Instance instance : oldInstances) {//遍歷老的實例集合,如果新的實例存在的話就更新
Instance instance1 = map.get(instance.toIPAddr());//獲取對應新的實例
if (instance1 != null) {//存在就更新
instance.setHealthy(instance1.isHealthy());
instance.setLastBeat(instance1.getLastBeat());
}
instanceMap.put(instance.getDatumKey(), instance);//放入映射
}
return instanceMap;
}
Cluster的init集羣初始化
即是開啓一個心跳檢查的任務,具體任務後面說。
public void init() {
if (inited) {
return;
}
checkTask = new HealthCheckTask(this);
HealthCheckReactor.scheduleCheck(checkTask);
inited = true;
}
DelegateConsistencyServiceImpl的put
實例創建好了,返回了新的實例集合,這個時候就去放到一致性服務裏了:
會根據傳進來的是臨時的還是永久的key
來選擇對應的服務。
下篇繼續將對應的服務怎麼處理實例集合。
好了,今天就到這裏了,希望對學習理解有幫助,大神看見勿噴,僅爲自己的學習理解,能力有限,請多包涵。