服务发现是 ZooKeeper 与 Dubbo、早期 Spring Cloud 的结合点:提供者建临时节点、消费者 watch 目录。这篇起几个真实的提供者进程,量上线与下线各要多久、下线期间消费者会发出多少失败请求、以及提供者「活着却被摘掉」之后会发生什么。
消费者看到的列表: ['127.0.0.1:7701', '127.0.0.1:7702', '127.0.0.1:7703', '127.0.0.1:7704', '127.0.0.1:7705']
/svc/orders/127.0.0.1:7701 的数据: {"port": 7701, "weight": 1} (临时节点,ephemeralOwner ≠ 0: True )从启动进程(含 Python 启动、连 ZooKeeper、建节点)到消费者看到它:80 ms
kill -9:消费者的列表在 3076 ms 后才去掉它;期间失败 9 次、成功 191 次;失败后立刻换一个实例重试成功 9 次 SIGTERM(进程被终止、连接断开但没有主动注销):消费者的列表 3464 ms 后去掉它;失败 20 次(进程被终止时没有注销节点:连接断了,但会话要等到超时才过期,节点才消失)
摘除延迟等于会话超时(3 s 内加上一点调度)。这期间消费者仍可能向已死的实例发请求,所以消费者要做失败重试或熔断,不能只靠注册中心。
主动 delete 节点后消费者 17 ms 内去掉它(进程仍在运行但已不再被调用,可以先摘流量、再关进程)
起始列表里有 7711、7712、7713: True
冻结 5 秒后列表里的这三个: [] (都因会话过期被摘除)
解冻 6 秒后三个进程都还活着: True | 重新出现在列表里的: {'naive': False, 'rereg_sync': False, 'rereg_thread': True}kazoo 状态监听器是在连接线程里回调的,如果在里面同步调用 create,我观察到节点没有被重新建立(我没有进一步查到根因,只确认了新开线程再调用就能成功)。无论用什么客户端,都要处理「会话过期后重新注册」。