• 1
  • 2
  • 3
  • 4
  • 5
云服务器安全 首 页  »  帮助中心  »  云服务器  »  云服务器安全
ZooKeeper真的low吗?上千节点场景配置服务讨论
发布日期:2016-2-13 9:2:36

  以下一次关于ZooKeeper为主的一次激烈的技术讨论。

  为什么说一套系统用了ZooKeeper,这个系统一定很low?

  ZooKeeper = low?

  提出此观点的架构师介绍其原因如下:

  在Docker环境下,通常虚机较多,我们发现ZooKeeper不能承受太多节点。我们的游戏平台是一个多租户场景,需频繁进行创建以及删除,在这种情况下若超过3,000虚拟机,ZooKeeper就不行了。

  当ZooKeeper挂了后,meta数据也会跟着丢了。Meta数据和和监控功能在ZooKeeper当初设计时并没有考虑的问题,因此后来我们打算自己造轮子,将这个需求实现。

  我也并非说ZooKeeper一无是处,ZooKeeper有它适合使用的场景,比如Hadoop那种场景ZooKeeper就可以工作得很好,但并不是所有场景都适用。Tim说过一句经典的话,Redis是把好锤子,但不能把所有存储的问题都当做钉子。ZooKeeper也是一样,不是所有的配置的问题都适合拿它来解决。

  其他一些网友的看法:

  Y: Kafka里使用ZooKeeper的方式有好几个地方可以借鉴。除了上面说的选一个master处理的方式外,为了避免订阅大量节点,也可以单设置一个变更节点,然后只订阅这个变更节点。

  G: Kafka集群依赖于ZooKeeper,但ZooKeeper也是Kafka的瓶颈。

  Z: 同意ZooKeeper是有很多运维的问题,一个解决方法是自己实现一个single node all in memory的lock service,然后运行在多个机器上,用ZooKeeper当作一个distributed lock来选一个master,这样ZooKeeper上的压力就小多了,而且不会随着集群大小增加而增加。

  某知名大型互联网公司方案:

  某知名大型互联网公司的架构师也基本认可上述观点,其新开发的服务框架中不再采用ZooKeeper作为注册中心,主要说明如下所示:

  1、 跨机房容灾方面,一旦出现机房间通信问题,另一个机房的部署的Observer节点,就不可读写了;

  2、 由于历史原因,ZooKeeper服务器与其他应用共用,40万+节点中60%是我们的,其他应用也是重度依赖zookeeper,互相之间有影响;

  3、 随着部署规模增大,客户端增多,ZooKeeper服务器中节点数量大增,核心ZooKeeper集群5台,每台服务器1,5000左右的长链接,近43万个节点,平均30余万watch。每个上线日,ZooKeeper服务器的流量都能上200mb/s,通过mntr的观察zk_outstanding_requests 经常达到300M以上;

  4、 ZooKeeper推送的频率、内容,我们自己不能控制,比如一个600 provider,12000 consumer的服务,如果新增一个provider,其实并不是每个consumer都需要通知的,但目前的机制下consumer监听一个目录,每个consumer都会得到一次provider列表推送;还有我们想在推送前根据一定的规则对provider列表做动态过滤排序,这个需求在zookeeper服务端也没法实现。

  5、 ZooKeeper客户端使用的是 172.17.xx.yy,172.17.xx.yz:2181 这样的ip串方式连接,后期想添加服务器分散主集群读写压力,也不好实现,因为需要更改地址串,需要update配置的客户端太多了;

  6、 有业务方报告,应用启动后连上ZooKeeper但一直读失败(读数据返回为null),也就是取服务列表失败,一段时间如半小时后自动恢复,查看zk server端日志,只看到一堆session过期的警告,没有其他异常;

  7、 provider约6万实例,consumer22万实例;

  基于以上原因,新方案实现也很简单,自己实现了一个服务用来做注册中心的,实现的是服务注册/订阅方面的功能。它负责接收长链接并推送,数据存储在MySQL。

  Q:使用ZooKeeper主要是它实现了强一致性,你这个注册中心是单点的吧?master election用ZooKeeper?注册中心会成为新的瓶颈和故障点?

  A:性能方面完全够用,因为这个服务也是集群部署的,客户端首先访问一个http接口拿到所有服务器的地址,并优先访问本机房的注册中心。注册中心基本读多写少,内存里面也缓存provider列表,不会有太大压力到MySQL;存储上通过MySQL实现一致性保证。

  Q:跨机房容灾方面有什么优化吗?如果网络没有足够的redundency,一旦出现network partiton,那么有一个机房就没办法到quorum了?

  A:通过多机房部署,每个机房保证至少2个节点,本机房挂了还可以访问其它机房,并且在客户端本地还有缓存文件。

  Q:当配置变化,client以http轮询方式去感知吗?

  A:Session过期那个,开始我们设的是很短,后来发现不对,网络一闪断,大量掉节点。现在我们自己实现的服务,半分钟一心跳,几个心跳没收到我才认为下线了。如果provider列表发生变化,我这边服务端会主动推送的,因为用的是TCP长连接。

  Q: Client有没有主动发现本地cache与服务端数据不一致的机制?例如当provider列表发生变化且服务端通过TCP长连给client推送失败的场景。

  A:有,我们心跳带本地版本号的,如果与服务端不一致的话,会触发服务端再次推送;

  另一知名大型互联网公司ZooKeeper运行现状

  而另外一知名大公司架构师认为如果consumer数量没有那么多,用ZooKeeper也较好满足要求。其业务场景的ZooKeepr使用及运行情况如下所示:

  线上的单个ZooKeeper节点平均连接数是6K,watcher是30万,netIO不高,ZooKeeper的机器配置比较差,用的是4G 4CPU 的虚拟机,5个节点,最多的consumer不超过200,平均consumer数量就5,6个左右。

  目前线上provider数3万左右实例数,consumer数10万左右,目前运行的没什么问题。3万个,如果每个服务10个实例,也就3,000个服务,全公司的,也没多少。看起来是多了点。 跟公司发展历史及使用场景关系很大。

  之前关于ZooKeeper踩坑最多的是在客户端上,最开始用的是netflix的curator(后来贡献给apache,但是我们用的是老的,没升级),遇到网络闪断重连不上,然后死循环一样,升级到apache curator就好了。

  后来遇到一个问题是,如果注册watcher太多,发生重连的时候,zk client会自动注册之前的所有watcher,这样会导致一个包的大小超过1M,然后也就重连不上又不断地重连,后来hack了zk client解决了这个问题,这个bug到目前为止zk官方仍然没有修复。

  不过这些坑基本上遇到一个可以解决一个,但是目前有一个问题目前也没找到好的解决方案,那就是业务方系统load变高,或者发生长时间gc,导致zk重连甚至session过期。

  另外关于zk连接,我们在最底下做了连接共享,因为好多服务都依赖zk,这个也降低了不少连接数。