`
san_yun
  • 浏览: 2655222 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

采用zookeeper的EPHEMERAL节点机制实现服务集群的陷阱

阅读更多

笔者在一个Websocket中间件产品(Apush,https://market.aliyun.com/products/56928004/cmapi020699.html#sku=yuncode1469900000)的集群管理中使用了zk的EPHEMERAL节点机制。
在编码过程中发现很多可能存在的陷阱,毛估估,第一次使用zk来实现集群管理的人应该有80%以上会掉坑,有些坑比较隐蔽,在网络问题或者异常的场景时才会出现,可能很长一段时间才会暴露出来。

1、不处理zk的连接状态变化事件导致zk客户端断开后与zk服务器集群没有重连。后果:连接丢失后EPHEMERAL节点会删除并且客户端watch丢失。

此坑不深,稍微注意一下还是容易发现的,并且采用Curator会减少此类问题的发生,不是完全避免,具体见第6个坑。

zk客户端如果和某台zk服务器断开,会主动尝试与zk集群中其他服务器重新连接,直到sessiontimeout,需要考虑极端的情况下出现sessiontimeout的处理。
zk客户端和zk服务器断开时会收到state为Disconnected的连接事件,此事件一般可以不处理,此事件后续会跟Expired状态的连接事件或者synconnected状态的连接事件。
zk客户端连接重试失败并且达到sessiontimeout时间则会收到Expired状态的连接事件,在此事件中应该由应用程序重试建立zk客户端。

2、在synconnected事件中创建EPHEMERAL节点没有判断此节点是否已经存在,在已经存在的情况下没有判断是否应该删除重建,后果:EPHEMERAL节点丢失导致可用的服务器不在可用服务器列表中。

此坑是个深坑,很隐蔽,而且没看到文章来提醒此坑。一般也不会出现问题,除非服务异常终止后立即重启。

一般我们会synconnected状态的连接事件中创建EPHEMERAL节点,注册watch。
synconnected状态的连接事件中处理EPHEMERAL节点可以分三种场景:
1、在第一次连接建立时
2、在断开连接后,sessiontimeout以前客户端自动重连成功
3、老的客户端没有正常调用close进行关闭,并且在此客户端sessiontimeout以前,创建了一个新的客户端
先说明一下第3种场景,session是否过期是由server判断的,如果客户不是调用close来和服务器主动断开,服务端会等客户端重连,直到session timeout。因此可能出现老session未过期,新客户端来建新session的情况。

在第2和第3种场景下,EPHEMERAL节点都会在服务端存在。
第3种场景下,随着残留在zk服务端session的timeout,老的EPHEMERAL节点会被自动删除。
由于zk的每个session都产生一个新的sessionId,为了区分第2、3种场景,必须在每次synconnected状态的连接事件中比较当前sessionId和上次sessionId。
在synconnected状态的连接事件中要同时判断sessionId是否变化以及EPHEMERAL节点是否已经存在。
对sessionId发生了变化且EPHEMERAL节点已经存在的情况要先删除后重建,这个是使用Curator也避免不了的。

3、应用程序关闭时不主动关闭zk客户端,后果:导致可用服务器列表包含已经失效的服务器。

原因同第2条,会导致EPHEMERAL节点在sessiontimeout之前都存在。
如果sessiontimeout时间很长的话,会导致整个集群的可用服务列表长时间包含已关闭的服务器。

4、创建一个zk客户端时,zk客户端连接zk服务器是异步的,如果在连接还没有建立时就调用zk客户端会抛异常。

正确的做法是在synconnected状态的连接事件中进行连接后的处理或者阻塞线程在连接事件中通知取消阻塞。
Curator提供了连接时同步阻塞的功能,可以避免此问题。

5、在zk的事件中执行长时间的业务

所有的zk事件都在EventThread中按顺序执行,如果一个事件长时间执行会导致其他事件无法及时响应。

6、使用2.X版本的Curator时,ExponentialBackoffRetry的maxRetries参数设置的再大都会被限制到29:MAX_RETRIES_LIMIT。

这个坑真不知道Curator是怎么想的,文档里一般也没提到这个坑。重试次数不够导致机房断网测试时zk的客户端可能永久丢失连接,据说新版本里已经增加了ForeverRetry。最后我放弃了Curator回到原生zk客户端。

关键概念:

  1. zk内部两个后台线程:IO和心跳线程(SendThread),事件处理线程(EventThread),均为单线程,且互相独立。所以eventthread堵塞,不会导致心跳超时;另外由于event thread单线程,如果在process过程中堵塞,其他事件即使发生了,也只会放到本地队列中,暂时不会执行。
  2. 如果client与zkserver连接中断,client的sendthread会使用原来的sessionid一直尝试重连,连上后server判断该sessionid是否已经过期,如果未过期,则SyncConnected会通知给client,同时期间的watcher事件也会通知给client,不会丢失;如果已过期,则client会收到到Expired状态的连接事件,sendthread, eventthread都退出,当前client失效。
  3. session是否过期是由server判断的;如果过期了则client使用原来的sessionid连接进来时,会收到expired状态的连接事件。由server来判断session是否过期主要是因为server需要清理该session相关的emphemeral节点并且通知其他客户端;如果由client判断再通知server,在client被直接kill掉的情况下,client创建的临时节点就清理不掉了;如果client和server各自判断,会有同步问题。
  4. 一个zk客户端连接断开后只要在session超时期限内重连成功,session会保持。
  5. 注册的watch事件和EPHEMERAL临时节点和session关联和连接没有关系。
  6. 客户端连接没有close就断开,服务端session仍然存活直到session超时。

原生zk客户端的连接事件里面几个关键状态

  • SyncConnected 连接成功和重连成功时触发
  • Disconnected 连接断开时触发
  • Expired session过期时触发

Curator的连接事件里面几个关键状态

  • CONNECTED 第一次连接
  • SUSPENDED 对应原生的Disconnected
  • LOST 对应原生的Expired
  • RECONNECTED 包括sessionid不变的重连和sessionid变化的重连,如果客户端建立了EPHEMERAL节点,必须在此事件中判断sessionId。
    对应sessionId不变的情况,连接断开期间watch的事件不会丢失,如果sessionId变化,则期间watch的事件会丢失。

 

原文:https://yq.aliyun.com/articles/227260

分享到:
评论

相关推荐

    MAC上查看Zookeeper节点工具

    在Zookeeper中,节点分为持久节点(PERSISTENT)、临时节点(EPHEMERAL)和顺序节点(SEQUENTIAL)。ZooInspector可以帮助你直观地识别这些不同类型的节点。 7. **监控Zookeeper状态**: 虽然ZooInspector主要是...

    zookeeper之节点基本操作.zip

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终将简单易用的接口和性能高效、功能稳定的系统提供给用户。...

    zookeeper之节点基本操作(一),节点znodes

    除了上述的基本节点类型外,ZooKeeper 还提供了其他重要的特性,包括但不限于 Watcher 机制和节点访问控制。 ##### 5. Watcher 机制 Watcher 机制允许客户端注册监听器来监视节点的状态变化。当节点的状态发生变化...

    zookeeper节点类型和java客户端创建zk节点

    Zookeeper是Apache软件基金会的一个开源项目,它是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步...

    zookeeper之节点基本操作.docx

    ### ZooKeeper之节点基本操作详解 #### 一、概述 ZooKeeper 是一款开源的分布式协调服务,由雅虎公司研发并开源,现已成为 Apache 软件基金会下的顶级项目。它主要解决分布式环境中常见的协调问题,如配置管理、...

    zookeeper分布session式实现

    - **高可用性保证:** 通过ZooKeeper集群提供的选举机制,可以确保即使部分节点故障,整个系统仍然能够正常运行,提供服务。 #### 5. 实战案例分析 为了更好地理解如何利用ZooKeeper实现分布式Session,我们可以...

    ZooKeeper 节点类型1

    ZooKeeper 是一个分布式协调服务,它通过提供一种树形的数据结构来管理分布式系统中的配置信息、命名服务、集群同步等。在这个数据结构中,每个节点都有特定的生命周期和属性,其中最重要的属性就是节点的类型。节点...

    zookeeper 分布式锁的实现1

    总之,Zookeeper 的分布式锁机制通过其独特的节点类型、事件通知和原子操作,为分布式系统提供了可靠、高效的锁服务。这种服务对于解决分布式环境中的并发控制问题至关重要,尤其是在高并发、高可用性要求的场景下。

    zk分布式锁1

    其中,临时节点和ephemeral节点可以被用来实现分布式锁。 临时节点实现分布式锁 临时节点是一种特殊的节点,它可以被用来实现分布式锁。当一个客户端创建一个临时节点时,如果该节点已经存在,则客户端可以等待该...

    ZooKeeper 23 道面试题及答案.docx

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口...

    zookeeper在线注册服务查看工具

    2. **查找服务故障**:当服务出现异常时,可以通过工具快速定位到可能存在问题的服务节点,检查其状态(如ephemeral、sequential标志)和数据内容。 3. **清理服务**:在测试环境中,可能需要定期清理Zookeeper中的...

    Zookeeper基础知识、体系结构、数据模型、服务器集群.docx

    Zookeeper是一个分布式协调服务,广泛应用于大数据领域,用于提供诸如数据一致性、命名服务、配置管理、集群管理和分布式锁等核心功能。它的设计基于一个类似文件系统的数据模型,并且具有严谨的分布式协议,确保在...

    Zookeeper面试题 28道.pdf

    Zookeeper 是一个开放源码的分布式协调服务,提供了一个集群管理者,监视着集群中各个节点的状态,并根据节点提交的反馈进行下一步合理操作。Zookeeper 保证了五个分布式一致性特性:顺序一致性、原子性、单一视图、...

    zookeeper面试专题1

    它是一个集群管理者,能够监控并管理集群中各个节点的状态,确保服务的稳定性和一致性。Zookeeper的核心特性包括高可用性、顺序一致性以及简单的API。 1. ZooKeeper是什么? Zookeeper是一个分布式的协调框架,它...

    zookeeper入门练习demo

    1. **临时节点特性**:临时节点在创建它的客户端会话结束时自动删除,常用于实现短暂的服务发现和会话管理。 2. **选举主节点**:在分布式环境中,临时节点常用于选举主节点,当主节点消失,临时节点被删除,其他...

    深入解析Zookeeper:核心特性与节点类型全景剖析

    Zookeeper 是一个强大的分布式协调框架,源于 Apache Hadoop 项目,专门解决分布式应用中的数据管理问题,如统一命名服务、状态同步、集群管理和配置管理。它的核心特性包括一个基于内存的文件系统数据结构和高效的...

    ZooKeeper面试题(2022最新版)-重点.docx

    ZooKeeper采用类似文件系统的多层级节点命名空间,其中每个节点称为znode。每个znode都可以存储数据,并且支持数据的读写操作。不同于传统的文件系统,ZooKeeper中的节点不仅可以存放数据,而且可以作为目录节点使用...

    zookeeper 集群配置

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终将简单易用的接口和性能高效、功能稳定的系统提供给用户。...

    java中的zookeeper

    Java中的ZooKeeper是一个分布式协调服务,由Apache Hadoop项目开发,主要用于解决大规模分布式系统中的命名服务、配置管理、集群同步等问题。它提供了一种基于分布式数据一致性模型的树状数据结构,使得多个应用程序...

    zookeeper笔记

    具体来说,只要集群中有超过一半的节点处于活动状态,集群就可以继续提供服务。这意味着如果集群有偶数个节点,则至少需要一半加一的节点存活才能保证集群的正常运行;如果有奇数个节点,则只需要一半以上的节点存活...

Global site tag (gtag.js) - Google Analytics