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
来选择对应的服务。
下篇继续将对应的服务怎么处理实例集合。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。