[alibaba/nacos]不懂就问....

2024-07-18 924 views
6

为什么一次注册流程 要用事件发布机制 又使用delaytaskEngine 然后又使用 dispatchAndExcuteTask 小弟看的绕来绕去, 求解为什么这么设计!!! image image image image image image

回答

3

其实说来说去就是为了这么几个方面,异步,解耦,模块化,提高吞吐量。 举个例子,服务注册,如果不用事件机制异步化,那么任何一个客户端,都必须等待服务注册的全流程走完,即使不考虑并发问题和互斥访问的问题,光是服务注册的全流程就能让客户端等的黄花菜都凉了。引入事件机制,客户端只需要在事件发布出去之后就可以返回了,之后怎么处理这个事件(整理服务注册数据,建立索引,写入内存,distro同步,失败重试),客户端不需要关心。更进一步,每一个操作都没有必要同步执行,抽象成task,交给统一的taskEngine就完事了,异步化和解耦就完成了。异步化让吞吐量更高,解耦让代码分层、模块化、职责明晰,既方便开发维护又方便后续替换升级。得,再说下去就是背八股文了,多用一下就能感受到了。

1

事件机制 和 封装taskengine 是为了异步解耦 模块化,那我还有个不明白的地方 如果中间的某个组件处理失败了, 或者服务宕机了,但是对与客户端来说 ,他是认为注册成功了,这样感觉是不是有点不妥?或者我的理解可能不对, 望大佬赐教! @MajorHe1

5

客户端认为注册成功了,这样没有问题。 1、如果服务是CP的,那必然要等到集群内所有的节点都同意写入了才会成功返回。如果服务是AP的,那必然要面临短期不一致的问题,服务端只能保证最终一致性。 2、服务端节点正常工作,那么nacos对于执行失败的任务会不断重试,直到成功或条件不再满足为止。例如distro同步,失败了则重试,直到成功或者目标节点离开集群为止。 3、服务端节点宕机,客户端会感知到http访问不通(1.X版本)或者grpc连接断开(2.X版本),之后重新选择集群内其他节点重新注册

4

感谢大佬,我继续阅读...

9

@MajorHe1 何老师您好,关于“3、服务端节点宕机,客户端会感知到http访问不通(1.X版本)或者grpc连接断开(2.X版本),之后重新选择集群内其他节点重新注册”这点。

如果有5个服务提供者长连接(grpc)到nacos服务端集群某节点,服务消费者订阅这5个服务提供者,突然服务端节点宕机。这时,会导致5个服务提供者重新注册,那么服务消费者缓存中,短时间内收到订阅推送事件,可能的情况是缓存中有5个实例,接受一次推送变成0,然后是1,最后恢复成5的情况呢?有一个数据抖动的过程?有数据保护吗?

3

客户端是有默认的数据保护机制的,但是只是防止空推送或者错误推送,数据抖动的过程可能还是会存在的,当然我没有实际测过,只是从逻辑上推断。 @lpaz010 image

6

@MajorHe1 非常谢谢何老师~,通过对ServiceInfoHolder#isEmptyOrErrorPush的解读了解以下情况,客户端就认为推送无效。

  1. 服务端推送的服务实例(hosts)为null或空集合时;
  2. 客户端开启空服务保护(pushEmptyProtection)后,下属情况过滤后,还是不存一个或多个服务实例时。
    • 情况1:服务端没有提前设置好是所有服务实例;
    • 情况2:过滤不健康的服务实例;
    • 情况3:过滤权重小于0的服务实例;
3

@MajorHe1 何老师您好,再问您一个问题吧:D 版本:develop分支最新 测试条件:将NamingClientProxyDelegate中初始化grpcClientProxy注释掉,所有网络请求走httpClientProxy和基于udp的PushReceiver来接收推送, 测试目的:v2版不使用长连接只使用短链接,观察使用短链接和使用长连接是否一致的表现,发现订阅服务那里情况并不一致。 您有测这里吗?

8

不要这么客气,大家都是共同学习进步 :) 客户端的空服务保护是默认不开启的,除非显示指定。

0

1、 仅仅注释掉grpcClientPorxy应该是不够的吧 image

2、 要http订阅服务,通过NamingClientProxyDelegate是行不通的,除非显示使用NamingHttpClientProxy

3、我没有测过这里,如果确有问题,建议新开ISSUE讨论

6

OK,收到。