9
这里 先get再watch,在两个执行过程中,如果刚好有新的服务在load之后、watch之前注册了,那这个服务可能不会被发现,可以尝试在 load 与 watch 中间加 sleep 进行测试复现
c.load(cli, key)
c.watchGroup.Run(func() {
c.watch(cli, key)
})
这里 先get再watch,在两个执行过程中,如果刚好有新的服务在load之后、watch之前注册了,那这个服务可能不会被发现,可以尝试在 load 与 watch 中间加 sleep 进行测试复现
c.load(cli, key)
c.watchGroup.Run(func() {
c.watch(cli, key)
})
这里,建议注册流程先加分布式锁,然后Get判断是否已经被注册,没被注册再Put注册。不加锁可能人工、自动发布之类的误操作会多个相同信息的服务注册互相覆盖了注册信息,如果是同一IP节点又没有reuseport,可能会有一个服务listen failed成为僵尸或者莫名的error日志不好排查;不判断是否存在就直接Put覆盖之前的也是不太能保证一致性。
没有看全部的代码流程,只是市面上大部分人实现的服务注册与发现可能都忽略了这两个问题所以来建议下,尤其是大规模集群节点数量多,可能会导致调度时服务注册与发现这种小概率分布式并发竞态产生不一致的问题,如果工程上(包括人工)操作可以避免,那问题不大,但是如果代码能加以更准确的保障可能会更好些
etcd的锁官方已经实现了现成的:
这里加了时间戳,同一个key注册两次会是两个key,然后我们所有服务listen fail是起不来的
这个情况即使对服务也没啥大影响,因为一个服务没有请求过来,其它pod依然可以接受请求,还有水平伸缩保障,这个是可以接受的问题,要处理这个情况就要让代码复杂不少,这个情况我觉得不需要处理
好的