3、开始使用ZooKeeper
3.2、第一个ZooKeeper会话
- 使用ZooKeeper中bin/目录下的zkServer和zkCi工具进行调试和管理。
- 使用客户端建立一个会话
]# zkCli.sh -- ... --客户端启动程序来建立一个会话。 2021-12-22 09:37:37,464 [myid:] - INFO [main:ZooKeeper@868] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@73a8dfcc 2021-12-22 09:37:37,476 [myid:] - INFO [main:X509Util@79] - Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation 2021-12-22 09:37:37,492 [myid:] - INFO [main:ClientCnxnSocket@237] - jute.maxbuffer value is 4194304 Bytes 2021-12-22 09:37:37,505 [myid:] - INFO [main:ClientCnxn@1653] - zookeeper.request.timeout value is 0. feature enabled= --客户端尝试连接到localhost/127.0.0.1:2181 2021-12-22 09:37:37,518 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1112] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) Welcome to ZooKeeper! JLine support is enabled --客户端连接成功,服务器开始初始化这个新会话。 2021-12-22 09:37:37,675 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@959] - Socket connection established, initiating session, client: /127.0.0.1:35332, server: localhost/127.0.0.1:2181 --会话初始化成功完成。会话ID(sessionid)是0x20000103b190002 2021-12-22 09:37:37,710 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x20000103b190002, negotiated timeout = 30000 WATCHER:: ----服务器向客户端发送一个SyncConnected事件。 WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2181(CONNECTED) 0]
- 简单使用会话
--列出根(root)下的所有znode。此刻出/zookeeper之外,znode树为没有其他znode [zk: localhost:2181(CONNECTED) 0] ls / [zookeeper] --创建一个名为/workers的znode [zk: localhost:2181(CONNECTED) 1] create /workers "" Created /workers --查看/workers [zk: localhost:2181(CONNECTED) 2] ls / [workers, zookeeper] [zk: localhost:2181(CONNECTED) 3] ls /workers [] --删除znode [zk: localhost:2181(CONNECTED) 4] delete /workers [zk: localhost:2181(CONNECTED) 5] ls / [zookeeper] --退出会话 [zk: localhost:2181(CONNECTED) 6] quit WATCHER:: WatchedEvent state:Closed type:None path:null 2021-12-22 09:56:02,382 [myid:] - INFO [main:ZooKeeper@1422] - Session: 0x20000103b190002 closed 2021-12-22 09:56:02,390 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@524] - EventThread shut down for session: 0x20000103b190002
4、一个主-从模式例子的实现
- 本示例仅用于教学目的,我们不建议使用zkCli.sh构建系统。
- 主-从模型中包括三个角色:
- Master(主节点):主节点负责监视新的从节点和任务,分配任务给可用的从节点。
- Worker(从节点):从节点会通过系统注册自己,以确保主节点看到它们可以执行任务,然后开始监视新任务。
- Client(客户端):客户端创建新任务并等待系统的响应。
4.1、主节点角色
- 因为只有一个进程会成为master,所以一个进程必须在ZooKeeper中锁定/master才能成为master。为此,进程会创建一个临时的znode,名为/master:
- 一个临时节点会在会话过期或关闭时自动被删除。
--开启第一个会话(zkCli.sh),将作为主节点会话 --创建名为/master的znode,以便获得管理权。使用-e标志来表示创建的znode为临时性的。 --添加主机信息并不是必需的,这样做仅仅是为了说明我们可以在需要时添加数据。 [zk: localhost:2181(CONNECTED) 0] create -e /master "master1.example.com:2223" Created /master --列出ZooKeeper树的根。 [zk: localhost:2181(CONNECTED) 1] ls / [master, zookeeper] --获取/master的数据。 [zk: localhost:2181(CONNECTED) 2] get /master master1.example.com:2223
- 假如其他进程想成为master,并尝试创建一个/master节点。让我们看看会发生什么:
- ZooKeeper告诉我们/master已经存在。这样,第二个进程就知道已经有一个master了。
--开启第二个会话(zkCli.sh),将作为从节点会话 [zk: localhost:2181(CONNECTED) 0] create -e /master "master2.example.com:2223" Node already exists: /master
- 主节点可能会崩溃,而从节点可能需要接替主节点的角色。为了检测到这一点,从节点需要在/master上设置一个监视点:
- stat命令可以得到znode节点的属性,并可以在已经存在的znode节点上设置监视点。-w选项表示添加监视点。
--第二个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 1] stat -w /master cZxid = 0x100000028 ctime = Wed Dec 22 23:06:11 CST 2021 mZxid = 0x100000028 mtime = Wed Dec 22 23:06:11 CST 2021 pZxid = 0x100000028 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x100004099d30008 dataLength = 24 numChildren = 0
- 在主节点崩溃的情况下,我们观察到以下情况:
- NodeDeleted事件指出主节点的会话已经关闭或过期。
--关闭第一会话,观察第二个会话 [zk: localhost:2181(CONNECTED) 2] WATCHER:: WatchedEvent state:SyncConnected type:NodeDeleted path:/master
- 主节点已经不存在了,现在从节点可以通过创建/master来成为主节点。
--第二个会话(将成为主节点会话) [zk: localhost:2181(CONNECTED) 2] create -e /master "master2.example.com:2223" Created /master
4.2、从节点,任务和任务分配
- 在讨论从节点和客户端所采取的步骤之前,先创建三个重要的父znode:/workers、/tasks和/assign。
- 这三个新的znode是持久的znode,不包含任何数据。在这个例子中,使用这些znode可以告诉我们哪些从节点是可用的,告诉我们什么时候有任务要分配,并向从节点分配任务。
--开启一个会话创建持久znode,创建后关闭该会话 [zk: localhost:2181(CONNECTED) 0] create /workers "" Created /workers [zk: localhost:2181(CONNECTED) 1] create /tasks "" Created /tesks [zk: localhost:2181(CONNECTED) 2] create /assign "" Created /assign
- 在实际的应用程序中,这三个znode需要由主进程在开始分配任务之前创建,或者由某个引导过程创建。无论它们是如何创建的,一旦它们存在,主节点需要监视/workers和/tasks的子znode的变化。
- ls命令使用-w选项表示在相应znode上设置监视点。
--第二个会话(目前是主节点会话) --监控/workers的变化 [zk: localhost:2181(CONNECTED) 3] ls -w /workers [] --监控/tesks的变化 [zk: localhost:2181(CONNECTED) 4] ls -w /tasks []
4.3、从节点角色
- 从节点第一步是通知主节点它可以执行任务了。它通过在/workers下创建一个临时的znode来表示它。从节点使用主机名来标识自己。
--重新开启第一个会话(zkCli.sh),将作为从节点会话 [zk: localhost:2181(CONNECTED) 0] create -e /workers/worker1.example.com "worker1.example.com:2223" Created /workers/worker1.example.com
- 之前主节点已经监视了/workers的子节点变化情况。一旦从节点在/workers下创建了一个znode,主节点就会观察到以下通知信息。
--第二个会话(目前是主节点会话) [zk: localhost:2181(CONNECTED) 5] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/workers
- 接下来,从节点需要创建一个父znode(/assing/worker1.example.com)来接收分配的任务。并通过ls命令的-w选项来监视这个节点的变化,以便等待新的任务。
--第一个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 1] create /assign/worker1.example.com "" Created /assign/worker1.example.com [zk: localhost:2181(CONNECTED) 2] ls -w /assign/worker1.example.com []
- 从节点现在已经准备就绪,可以接收分配的任务了
4.4、客户端角色
- 客户端向系统添加任务。就本例而言,任务是什么并不重要。这里我们假设客户端要求主从系统运行cmd命令。要向系统中添加任务,客户端需要执行以下操作:
--开启第三个会话(zkCli.sh),将作为客户端会话 [zk: localhost:2181(CONNECTED) 0] create -s /tasks/task- "cmd" Created /tasks/task-0000000000
- 我们需要按照任务添加的顺序来添加znode,其本质上是一个队列。客户端现在必须等待任务执行完毕。执行任务的从节点将任务执行完毕后,会在“/tasks/task-”下创建一个子znode来表示任务状态。客户端通过查看这个子znode是否创建来确定任务是否执行完毕,因此客户端需要监视“/tasks/task-”的创建事件。
--第三个会话(目前是客户端会话) [zk: localhost:2181(CONNECTED) 1] ls -w /tasks/task-0000000000 []
- 之前主节点已经监视了/tasks的子znode。一旦客户端在/tasks下创建了一个znode,主节点就会观察到以下通知信息。
--第二个会话(目前是主节点会话) [zk: localhost:2181(CONNECTED) 5] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks
- 主节点之后会检查这个新的任务,然后获取可用的从节点列表,并任务分配给可用的从节点。
--第二个会话(目前是主节点会话) [zk: localhost:2181(CONNECTED) 5] ls /tasks [task-0000000000] [zk: localhost:2181(CONNECTED) 6] ls /workers [worker1.example.com] [zk: localhost:2181(CONNECTED) 7] create /assign/worker1.example.com/task-0000000000 "" Created /assign/worker1.example.com/task-0000000000
- 从节点接收到分配任务的通知(之前从节点已经监视了/assign/worker1.example.com):
--第一个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 3] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/assign/worker1.example.com
- 从节点检查新任务,并确认该任务是否分配给自己:
--第一个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 3] ls /assign/worker1.example.com [task-0000000000]
- 一旦从节点完成任务的执行,它就会在“/tasks/task-”中添加一个表示状态的znode:
--第一个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 4] create /tasks/task-0000000000/status "done" Created /tasks/task-0000000000/status
- 客户端接收到任务执行完成的通知,并检查执行结果:
--第三个会话(目前是客户端会话) [zk: localhost:2181(CONNECTED) 2] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks/task-0000000000 [zk: localhost:2181(CONNECTED) 2] get /tasks/task-0000000000 cmd [zk: localhost:2181(CONNECTED) 3] get /tasks/task-0000000000/status done
- 客户端检查状态znode的内容,并确认任务的执行结果。在本例中,它已经成功执行,结果是“done”。当然任务也可能非常复杂,甚至涉及另一个分布式系统。最终不管是什么样的任务,执行任务和通过Zookeeper传递结果的机制,本质上都是一样的。
4.5、三个会话
4.5.3、第一个会话
--第一个会话(目前是主节点会话) [zk: localhost:2181(CONNECTED) 0] create -e /master "master1.example.com:2223" Created /master [zk: localhost:2181(CONNECTED) 1] ls / [master, zookeeper] [zk: localhost:2181(CONNECTED) 2] get /master master1.example.com:2223 --第一个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 0] create -e /workers/worker1.example.com "worker1.example.com:2223" Created /workers/worker1.example.com [zk: localhost:2181(CONNECTED) 1] create /assign/worker1.example.com "" Created /assign/worker1.example.com [zk: localhost:2181(CONNECTED) 2] ls -w /assign/worker1.example.com [] [zk: localhost:2181(CONNECTED) 3] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/assign/worker1.example.com [zk: localhost:2181(CONNECTED) 3] ls /assign/worker1.example.com [task-0000000000] [zk: localhost:2181(CONNECTED) 4] create /tasks/task-0000000000/status "done" Created /tasks/task-0000000000/status
4.5.2、第二个会话
--第二个会话(目前是从节点会话) [zk: localhost:2181(CONNECTED) 0] create -e /master "master2.example.com:2223" Node already exists: /master [zk: localhost:2181(CONNECTED) 1] stat -w /master cZxid = 0x100000004 ctime = Thu Dec 23 10:51:28 CST 2021 mZxid = 0x100000004 mtime = Thu Dec 23 10:51:28 CST 2021 pZxid = 0x100000004 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x1000011abdf0000 dataLength = 24 numChildren = 0 --第二个会话(目前是主节点会话) [zk: localhost:2181(CONNECTED) 2] create -e /master "master2.example.com:2223" Created /master [zk: localhost:2181(CONNECTED) 3] ls -w /workers [] [zk: localhost:2181(CONNECTED) 4] ls -w /tasks [] [zk: localhost:2181(CONNECTED) 5] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/workers [zk: localhost:2181(CONNECTED) 5] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks [zk: localhost:2181(CONNECTED) 5] ls /tasks [task-0000000000] [zk: localhost:2181(CONNECTED) 6] ls /workers [worker1.example.com] [zk: localhost:2181(CONNECTED) 7] create /assign/worker1.example.com/task-0000000000 "" Created /assign/worker1.example.com/task-0000000000
4.5.3、第三个会话
--第三个会话(目前是客户端会话) [zk: localhost:2181(CONNECTED) 0] create -s /tasks/task- "cmd" Created /tasks/task-0000000000 [zk: localhost:2181(CONNECTED) 1] ls -w /tasks/task-0000000000 [] [zk: localhost:2181(CONNECTED) 2] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks/task-0000000000 [zk: localhost:2181(CONNECTED) 2] get /tasks/task-0000000000 cmd [zk: localhost:2181(CONNECTED) 3] get /tasks/task-0000000000/status done
1
3、开始使用ZooKeeper
3.2、第一个ZooKeeper会话
- 使用ZooKeeper中bin/目录下的zkServer和zkCi工具进行调试和管理。
- 使用客户端建立一个会话
]# zkCli.sh -- ... --客户端启动程序来建立一个会话。 2021-12-22 09:37:37,464 [myid:] - INFO [main:ZooKeeper@868] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@73a8dfcc 2021-12-22 09:37:37,476 [myid:] - INFO [main:X509Util@79] - Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation 2021-12-22 09:37:37,492 [myid:] - INFO [main:ClientCnxnSocket@237] - jute.maxbuffer value is 4194304 Bytes 2021-12-22 09:37:37,505 [myid:] - INFO [main:ClientCnxn@1653] - zookeeper.request.timeout value is 0. feature enabled= --客户端尝试连接到localhost/127.0.0.1:2181 2021-12-22 09:37:37,518 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1112] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error) Welcome to ZooKeeper! JLine support is enabled --客户端连接成功,服务器开始初始化这个新会话。 2021-12-22 09:37:37,675 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@959] - Socket connection established, initiating session, client: /127.0.0.1:35332, server: localhost/127.0.0.1:2181 --会话初始化成功完成。会话ID(sessionid)是0x20000103b190002 2021-12-22 09:37:37,710 [myid:localhost:2181] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x20000103b190002, negotiated timeout = 30000 WATCHER:: ----服务器向客户端发送一个SyncConnected事件。 WatchedEvent state:SyncConnected type:None path:null [zk: localhost:2181(CONNECTED) 0]
- 简单使用会话
--列出根(root)下的所有znode。此刻出/zookeeper之外,znode树为没有其他znode [zk: localhost:2181(CONNECTED) 0] ls / [zookeeper] --创建一个名为/workers的znode [zk: localhost:2181(CONNECTED) 1] create /workers "" Created /workers --查看/workers [zk: localhost:2181(CONNECTED) 2] ls / [workers, zookeeper] [zk: localhost:2181(CONNECTED) 3] ls /workers [] --删除znode [zk: localhost:2181(CONNECTED) 4] delete /workers [zk: localhost:2181(CONNECTED) 5] ls / [zookeeper] --退出会话 [zk: localhost:2181(CONNECTED) 6] quit WATCHER:: WatchedEvent state:Closed type:None path:null 2021-12-22 09:56:02,382 [myid:] - INFO [main:ZooKeeper@1422] - Session: 0x20000103b190002 closed 2021-12-22 09:56:02,390 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@524] - EventThread shut down for session: 0x20000103b190002