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
来选择对应的服务。
下篇继续将对应的服务怎么处理实例集合。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。