架构设计 | 分布式系统调度,Zookeeper集群化管理
本文源码:github·点这里 || gitee·点这里
一、框架简介
1、基础简介
zookeeper基于观察者模式设计的组件,主要应用于分布式系统架构中的,统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等场景。
2、集群选举
zookeeper集群基于半数机制,集群中半数以上机器存活,集群处于可用状态。所以建议zookeeper集群安装为奇数台服务器。在集群的配置文件中并没有指定master和slave。在zookeeper工作时,是有一个节点为leader,其他则为follower,leader是通过内部的选举机制临时产生的。
基本描述
假设有三台服务器组成的zookeeper集群,每个节点的myid编号依次1-3,依次启动服务器,会发现server2被选择为leader节点。
server1启动,执行一次选举。服务器1投自己一票。此时服务器1票数一票,未达到半数以上(2票),选举无法完成,服务器1状态保持为looking;
server2启动,再执行一次选举。服务器1和2分别投自己一票,并交换选票信息,因为服务器2的myid比服务器1的myid大,服务器1会更改选票为投服务器2。此时服务器1票数0票,服务器2票数2票,达到半数以上,选举完成,服务器1状态为follower,2状态保持leader,此时集群可用,服务器3启动后直接为follower。
二、集群配置
1、创建配置目录
# mkdir -p /data/zookeeper/data # mkdir -p /data/zookeeper/logs
2、基础配置
# vim /opt/zookeeper-3.4.14/conf/zoo.cfg ticktime=2000 initlimit=10 synclimit=5 datadir=/data/zookeeper/data datalogdir=/data/zookeeper/logs clientport=2181
3、单节点配置
# vim /data/zookeeper/data/myid
三个节点服务,分别在myid文件中写入[1,2,3]
4、集群服务
在每个服务的zoo.cfg配置文件中写入如下配置:
server.1=192.168.72.133:2888:3888 server.2=192.168.72.136:2888:3888 server.3=192.168.72.137:2888:3888
5、启动集群
分别启动三台zookeeper服务
[zookeeper-3.4.14]# bin/zkserver.sh start starting zookeeper ... started
6、查看集群状态
mode: leader是master节点
mode: follower是slave节点
[zookeeper-3.4.14]# bin/zkserver.sh status mode: leader
7、集群状态测试
随便登录一台服务的客户端,创建一个测试节点,然后在其他服务上查看。
[zookeeper-3.4.14 bin]# ./zkcli.sh [zk: 0] create /node-test01 node-test01 created /node-test01 [zk: 1] get /node-test01
或者关闭leader节点
[zookeeper-3.4.14 bin]# ./zkserver.sh stop
则会重新选举该节点。
8、nginx统一管理
[rnginx-1.15.2 conf]# vim nginx.conf stream { upstream zkcluster { server 192.168.72.133:2181; server 192.168.72.136:2181; server 192.168.72.136:2181; } server { listen 2181; proxy_pass zkcluster; } }
三、服务节点监听
1、基本原理
分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线。
流程描述:
- 启动zookeeper集群服务;
- registerserver模拟服务端注册;
- clientserver模拟客户端监听;
- 启动服务端注册三次,注册不同节点的zk-node服务;
- 依次关闭注册的服务端,模拟服务下线流程;
- 查看客户端日志,可以监控到服务节点变化;
首先创建一个节点:serverlist,用来存放服务器列表。
[zk: 0] create /serverlist "serverlist"
2、服务端注册
package com.zkper.cluster.monitor; import java.io.ioexception; import org.apache.zookeeper.createmode; import org.apache.zookeeper.watchedevent; import org.apache.zookeeper.watcher; import org.apache.zookeeper.zookeeper; import org.apache.zookeeper.zoodefs.ids; public class registerserver { private zookeeper zk ; private static final string connectstring = "127.0.0.133:2181,127.0.0.136:2181,127.0.0.137:2181"; private static final int sessiontimeout = 3000; private static final string parentnode = "/serverlist"; private void getconnect() throws ioexception{ zk = new zookeeper(connectstring, sessiontimeout, new watcher() { @override public void process(watchedevent event) { } }); } private void registerserver(string nodename) throws exception{ string create = zk.create(parentnode + "/server", nodename.getbytes(), ids.open_acl_unsafe, createmode.ephemeral_sequential); system.out.println(nodename +" 上线:"+ create); } private void working() throws exception{ thread.sleep(long.max_value); } public static void main(string[] args) throws exception { registerserver server = new registerserver(); server.getconnect(); // 分别启动三次服务,注册不同节点,再一次关闭不同服务端看客户端效果 // server.registerserver("zk-node-133"); // server.registerserver("zk-node-136"); server.registerserver("zk-node-137"); server.working(); } }
3、客户端监听
package com.zkper.cluster.monitor; import org.apache.zookeeper.*; import java.io.ioexception; import java.util.arraylist; import java.util.list; public class clientserver { private zookeeper zk ; private static final string connectstring = "127.0.0.133:2181,127.0.0.136:2181,127.0.0.137:2181"; private static final int sessiontimeout = 3000; private static final string parentnode = "/serverlist"; private void getconnect() throws ioexception { zk = new zookeeper(connectstring, sessiontimeout, new watcher() { @override public void process(watchedevent event) { try { // 监听在线的服务列表 getserverlist(); } catch (exception e) { e.printstacktrace(); } } }); } private void getserverlist() throws exception { list<string> children = zk.getchildren(parentnode, true); list<string> servers = new arraylist<>(); for (string child : children) { byte[] data = zk.getdata(parentnode + "/" + child, false, null); servers.add(new string(data)); } system.out.println("当前服务列表:"+servers); } private void working() throws exception{ thread.sleep(long.max_value); } public static void main(string[] args) throws exception { clientserver client = new clientserver(); client.getconnect(); client.getserverlist(); client.working(); } }
四、源代码地址
github·地址 https://github.com/cicadasmile/data-manage-parent gitee·地址 https://gitee.com/cicadasmile/data-manage-parent
推荐阅读:数据和架构管理
推荐阅读