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


ip1 和 ip10 相对其它 8 个节点{ip2…ip9} , 请求流量小了一点 , 但很明显 , 在分布式系统中 , 即使是对等部署的服务 , 因为请求到达的时间 , 硬件的状态 , 操作系统的调度 , 虚拟机的 GC 等 , 任何一个时间点 , 这些对等部署的节点状态也不可能完全一致 , 而流量不一致的情况下 , 只要注册中心在 SLA 承诺的时间内(例如 1s 内)将数据收敛到一致状态(即满足最终一致) , 流量将很快趋于统计学意义上的一致 , 所以注册中心以最终一致的模型设计在生产实践中完全可以接受 。

  • 分区容忍及可用性需求分析
接下来我们看一下网络分区(Network Partition)情况下注册中心不可用对服务调用产生的影响 , 即 CAP 中的 A 不满足时带来的影响 。
考虑一个典型的 ZooKeeper 三机房容灾 5 节点部署结构 (即 2-2-1 结构) , 如下图:
当机房 3 出现网络分区 (Network Partitioned) 的时候 , 即机房 3 在网络上成了孤岛 , 我们知道虽然整体 ZooKeeper 服务是可用的 , 但是节点 ZK5 是不可写的 , 因为联系不上 Leader 。
也就是说 , 这时候机房 3 的应用服务 svcB 是不可以新部署 , 重新启动 , 扩容或者缩容的 , 但是站在网络和服务调用的角度看 , 机房 3 的 svcA 虽然无法调用机房 1 和机房 2 的 svcB, 但是与机房 3 的 svcB 之间的网络明明是 OK 的啊 , 为什么不让我调用本机房的服务?
现在因为注册中心自身为了保脑裂 (P) 下的数据一致性(C)而放弃了可用性 , 导致了同机房的服务之间出现了无法调用 , 这是绝对不允许的!可以说在实践中 , 注册中心不能因为自身的任何原因破坏服务之间本身的可连通性 , 这是注册中心设计应该遵循的铁律! 后面在注册中心客户端灾容上我们还会继续讨论 。
同时我们再考虑一下这种情况下的数据不一致性 , 如果机房 1 , 2 , 3 之间都成了孤岛 , 那么如果每个机房的 svcA 都只拿到本机房的 svcB 的 ip 列表 , 也即在各机房 svcB 的 ip 列表数据完全不一致 , 影响是什么?
其实没啥大影响 , 只是这种情况下 , 全都变成了同机房调用 , 我们在设计注册中心的时候 , 有时候甚至会主动利用这种注册中心的数据可以不一致性 , 来帮助应用主动做到同机房调用 , 从而优化服务调用链路 RT 的效果!
通过以上我们的阐述可以看到 , 在 CAP 的权衡中 , 注册中心的可用性比数据强一致性更宝贵 , 所以整体设计更应该偏向 AP , 而非 CP , 数据不一致在可接受范围 , 而 P 下舍弃 A 却完全违反了注册中心不能因为自身的任何原因破坏服务本身的可连通性的原则 。
服务规模、容量、服务联通性
你所在公司的“微服务”规模有多大?数百微服务?部署了上百个节点?那么 3 年后呢?互联网是产生奇迹的地方 , 也许你的“服务”一夜之间就家喻户晓 , 流量倍增 , 规模翻番!
当数据中心服务规模超过一定数量 (服务规模 =F{服务 pub 数, 服务 sub 数}) , 作为注册中心的 ZooKeeper 很快就会像下图的驴子一样不堪重负
其实当 ZooKeeper 用对地方时 , 即用在粗粒度分布式锁 , 分布式协调场景下 , ZooKeeper 能支持的 tps 和支撑的连接数是足够用的 , 因为这些场景对于 ZooKeeper 的扩展性和容量诉求不是很强烈 。
但在服务发现和健康监测场景下 , 随着服务规模的增大 , 无论是应用频繁发布时的服务注册带来的写请求 , 还是刷毫秒级的服务健康状态带来的写请求 , 还是恨不能整个数据中心的机器或者容器皆与注册中心有长连接带来的连接压力上 , ZooKeeper 很快就会力不从心 , 而 ZooKeeper 的写并不是可扩展的 , 不可以通过加节点解决水平扩展性问题 。

推荐阅读