Nacos面试
# Nacos面试
# 1.Nacos服务注册表结构是怎样的?
分级存储模型:namespace命名空间(生产环境/测试环境...)>分组group>服务>集群(上海/北京...)
- 在ServiceManager类下,Map<String ,Map<String ,Service>>中的基本类型对应Map(namespace,Map(group@@servicename,Service)),每个namespace对应一个不同组的微服务Map
- 每个Service服务类下面又维护一个Map<String,Cluster>,对应集群key和集群实体。
- 每个Cluster类下,又维护了一个Set<Instance>,代表微服务实例。
# 2.Nacos如何支持数十万服务注册压力
①异步更新本地注册表②同步到Nacos集群中的其他节点
Nacos收到服务注册请求时,不会立即写数据,而是把服务注册的任务放入一个阻塞队列,然后就立即响应给客户端。然后利用线程池读取阻塞队列中的任务,异步完成实例更新,提高并发写能力。
阻塞队列没有元素时会进入wait状态等待新的元素,线程释放CPU执行权,直到新的元素来唤醒。
public void run() {
Loggers.DISTRO.info("distro notifier started");
// 死循环,不断执行任务。因为是阻塞队列,不会导致CPU负载过高
for (; ; ) {
try {
// 从阻塞队列中获取任务
Pair<String, DataOperation> pair = tasks.take();
handle(pair);
} catch (Throwable e) {
Loggers.DISTRO.error("[NACOS-DISTRO] Error while handling notifying task", e);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3.Nacos如何解决并发读写冲突
- 在添加实例函数中,对service对象添加了synchronized同步锁,对于同一个服务的多个实例只能够串行来完成注册。
- Nacos在更新实例列表时,会采用CopyOnWrite技术,首先将旧的实例列表拷贝一份,然后更新拷贝的实例列表,而此时读的还是旧的实例列表,最后再用更新后的实例列表拉覆盖旧的实例列表。
- 更新拷贝的旧实例列表的过程:①ips首先和旧实例列表求交集,得到需要更新的实例列表,然后将旧实例的健康状态更新到新的实例。②ips-旧实例列表,得到新增的实例列表。③旧实例列表-ips,得到需要删除的实例列表。
# 4.Nacos和Eureka区别
Nacos实例分为永久实例和临时实例,临时实例是基于心跳监测,而永久实例基于主动监测。
Eureka心跳只有临时实例,支支持心跳模式。
服务发现上面Nacos支持定时拉取和订阅推送;Eureka只支持定时拉取。
订阅机制:客户端每6s通过一个定时任务从注册中心获取实例列表,当发现实例发生变化,发布变更事件,发送UDP广播给所有订阅者,订阅者进行实例更新、更改本地缓存。
#
编辑 (opens new window)
上次更新: 2023/12/15, 15:49:57