dubbo提供者配置 zookeeper和dubbo原理( 四 )


这需要注册中心仔细的设计自己提供的客户端 , 客户端中应该有针对注册中心服务完全不可用时做容灾的手段 , 例如设计客户端缓存数据机制(我们称之为 client snapshot)就是行之有效的手段 。另外 , 注册中心的 health check 机制也要仔细设计以便在这种情况不会出现诸如推空等情况的出现 。
ZooKeeper 的原生客户端并没有这种能力 , 所以利用 ZooKeeper 实现注册中心的时候我们一定要问自己 , 如果把 ZooKeeper 所有节点全干掉 , 你生产上的所有服务调用链路能不受任何影响么?而且应该定期就这一点做故障演练 。
你有没有 ZooKeeper 的专家可依靠?ZooKeeper 看似很简单的一个产品 , 但在生产上大规模使用并且用好 , 并不是那么理所当然的事情 。如果你决定在生产中引入 ZooKeeper , 你最好做好随时向 ZooKeeper 技术专家寻求帮助的心理预期 , 最典型的表现是在两个方面:

  • 难以掌握的 Client/Session 状态机
ZooKeeper 的原生客户端绝对称不上好用 , Curator 会好一点 , 但其实也好的有限 , 要完全理解 ZooKeeper 客户端与 Server 之间的交互协议也并不简单 , 完全理解并掌握 ZooKeeper Client/Session 的状态机(下图)也并不是那么简单明了:
但基于 ZooKeeper 的服务发现方案却是依赖 ZooKeeper 提供的长连接 /Session 管理 , Ephemeral ZNode , Event&Notification, ping 机制上 , 所以要用好 ZooKeeper 做服务发现 , 恰恰要理解这些 ZooKeeper 核心的机制原理 , 这有时候会让你陷入暴躁 , 我只是想要个服务发现而已 , 怎么要知道这么多?而如果这些你都理解了并且不踩坑 , 恭喜你 , 你已经成为 ZooKeeper 的技术专家了 。
  • 难以承受的异常处理
我们在阿里巴巴内部应用接入 ZooKeeper 时 , 有一个《ZooKeeper 应用接入必知必会》的 WIKI , 其中关于异常处理有过如下的论述:
如果说要选出应用开发者在使用 ZooKeeper 的过程中 , 最需要了解清楚的事情?那么根据我们之前的支持经验 , 一定是异常处理 。
当所有一切(宿主机 , 磁盘 , 网络等等)都很幸运的正常工作的时候 , 应用与 ZooKeeper 可能也会运行的很好 , 但不幸的是 , 我们整天会面对各种意外 , 而且这遵循墨菲定律 , 意料之外的坏事情总是在你最担心的时候发生 。
所以务必仔细了解 ZooKeeper 在一些场景下会出现的异常和错误 , 确保您正确的理解了这些异常和错误 , 以及知道您的应用如何正确的处理这些情况 。
ConnectionLossException 和 Disconnected 事件
简单来说 , 这是个可以在同一个 ZooKeeper Session 恢复的异常 (Recoverable), 但是应用开发者需要负责将应用恢复到正确的状态 。
发生这个异常的原因有很多 , 例如应用机器与 ZooKeeper 节点之间网络闪断 , ZooKeeper 节点宕机 , 服务端 Full GC 时间超长 , 甚至你的应用进程 Hang 死 , 应用进程 Full GC 时间超长之后恢复都有可能 。
要理解这个异常 , 需要了解分布式应用中的一个典型的问题 , 如下图:
在一个典型的客户端请求、服务端响应中 , 当它们之间的长连接闪断的时候 , 客户端感知到这个闪断事件的时候 , 会处在一个比较尴尬的境地 , 那就是无法确定该事件发生时附近的那个请求到底处在什么状态 , Server 端到底收到这个请求了么?已经处理了么?因为无法确定这一点 , 所以当客户端重新连接上 Server 之后 , 这个请求是否应该重试(Retry)就也要打一个问号 。
所以在处理连接断开事件中 , 应用开发者必须清楚处于闪断附近的那个请求是什么(这常常难以判断) , 该请求是否是幂等的 , 对于业务请求在 Server 端服务处理上对于”仅处理一次” “最多处理一次” “最少处理一次”语义要有选择和预期 。

推荐阅读