一、集群自启动脚本

  1.关闭zk

[root@localhost bin]# jps
Jps
QuorumPeerMain
[root@localhost bin]# kill -

  //kill或者stop都是可以的

  2.远程执行命令

[root@localhost bin]# ssh 192.168.137.138 /opt/zookeeper/zookeeper-3.4./bin/zkServer.sh start
root@192.168.137.138's password:
JMX enabled by default
Using config: /opt/zookeeper/zookeeper-3.4./bin/../conf/zoo.cfg
Starting zookeeper ... /opt/zookeeper/zookeeper-3.4./bin/zkServer.sh: 第 行:[: /tmp/zookeeper: 期待二元表达式
STARTED

  出现以上中文的地方只需要修改一下zoo.cfg,把多余的配置注释即可!

  当然,这样还是无法启动!因为ssh过去是以一个bash的方式过去的(不会执行/etc/profile,而正常登录是会执行的,也可以打开相应的脚本进行查看),也就是PATH不在了,导致JAVA_HOME等找不到了!

  EXPORT所定义的变量对自己所在的shell以及子shell生效

  这里就需要用到之前说到的source命令了:https://www.cnblogs.com/pkufork/p/linux_source.html

ssh 192.168.137.138 "source /etc/profile&&/opt/zookeeper/zookeeper-3.4.5/bin/zkServer.sh start"

  //如果不使用引号,将会以空格作为命令的分割!

  3.配置免密登录

  在其中一台机器上(这里是192.168.137.128)

ssh-keygen

  //之后enter即可

ssh-copy-id 192.168.137.128
ssh-copy-id 192.168.137.138
ssh-copy-id 192.168.137.148

  4.一键启动脚本

cd /root
mkdir bin
cd bin
vim startZK.sh
#!/bin/bash
SERVERS="192.168.137.128 192.168.137.138 192.168.137.148"
echo "start zk..."
for SERVER in $SERVERS
do
ssh $SERVER "source /etc/profile&&/opt/zookeeper/zookeeper-3.4.5/bin/zkServer.sh start"
done
chmod +x startZK.sh 

  这样,通过startZK.sh就能一键启动了!(/root/bin默认在PATH中了!)

二、zk的Java客户端

  相关API入门可以参考:https://www.cnblogs.com/ggjucheng/p/3370359.html

  第三方的客户端:zkclient参考:https://www.cnblogs.com/f1194361820/p/5575206.html

  1.引入maven依赖

        <dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>

  2.测试程序是否能通

public class SimpleZK {
// 设置连接字符串(可以用逗号隔开多个),失败时会自动尝试多个
private static final String coonectString = "192.168.137.128:2181,192.168.137.138:2181,192.168.137.148:2181";
// 超时时间
private static final int sessionTimeout = 2000;
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
ZooKeeper zkClient = new ZooKeeper(coonectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
// 收到通知事件后的回调函数
System.out.println(watchedEvent.getType()+"---"+watchedEvent.getPath());
}
});
// zk的增删改查(这里使用最底层的原生操作,zkclient的待补充)
String node = zkClient.create("/app2", "hellozk".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } }

  完美:

    

  3.增删改查实例

package com.zk;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test; import java.io.IOException;
import java.util.List; /**
* 测试zk的Java客户端
*
* @author zcc ON 2018/1/17
**/
public class SimpleZK {
// 设置连接字符串(可以用逗号隔开多个),失败时会自动尝试多个
private static final String coonectString = "192.168.137.128:2181,192.168.137.138:2181,192.168.137.148:2181";
// 超时时间
private static final int sessionTimeout = 2000;
// 初始变量
ZooKeeper zkClient = null; /**
* 初始化方法
* @throws IOException
*/
@Before
public void init() throws IOException {
zkClient = new ZooKeeper(coonectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
// 收到通知事件后的回调函数
System.out.println(watchedEvent.getType()+"---"+watchedEvent.getPath());
// 开启循环监听(监听调用此方法,此方法又开启监听)
try {
zkClient.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} /**
* 创建
*/
public void testCreate() throws IOException, KeeperException, InterruptedException {
String node = zkClient.create("/app2", "hellozk".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
} /**
* 判断是否存在节点
* @throws KeeperException
* @throws InterruptedException
*/
public void testExists() throws KeeperException, InterruptedException {
// stat就是zk中那一堆数据(null则不存在)
Stat stat = zkClient.exists("/", false);
}
/**
* 取得子节点
*/
@Test
public void testGetChildren() throws KeeperException, InterruptedException {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
} /**
* 获取数据
*/
@Test
public void testGetData() throws KeeperException, InterruptedException {
// 分别是路径,是否监听以及状态版本(null就OK了,取最新)
byte[] data = zkClient.getData("/app2", false, null);
System.out.println(new String(data));
} /**
* 删除数据
*/
@Test
public void testDeleteZnode() throws KeeperException, InterruptedException {
// -1作为版本号参数表示删除所有版本(上层的API是不用传这些参数的)
zkClient.delete("/app2",-1);
} /**
* 修改数据
*/
public void testSetData() throws KeeperException, InterruptedException {
zkClient.setData("/app2", "hellozkCli".getBytes(), -1);
}
}

三、应用实例

  1.分布式服务器动态上下线感知(主节点HA)

  大致原理:

    

  大致流程比较清晰,当服务器启动时就去注册信息(例如给出主机与id等信息),给出一个短暂的带序列号的临时节点,这样服务器下线的时候节点便被删除了;而客户端则是去zk获取子节点信息,得到服务器列表并且注册监听,这样当有节点发生改变时变可以感知变化了!

  2.Java代码

    IDEA中给main方法添加参数,参考:http://blog.csdn.net/u013713294/article/details/53020293

  服务都端:

package com.zk;

import org.apache.zookeeper.*;

import java.io.IOException;

/**
* 分布式服务器动态感知——服务端
*
* @author zcc ON 2018/1/17
**/
public class DistributedServer { private static final String coonectString = "192.168.137.128:2181,192.168.137.138:2181,192.168.137.148:2181";
private static final int sessionTimeout = 2000;
private static final String parentNode = "/servers"; private ZooKeeper zk = null; /**
* 获得连接
* @throws IOException
*/
public void getConn() throws IOException {
zk = new ZooKeeper(coonectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
// 收到通知事件后的回调函数
System.out.println(watchedEvent.getType()+"---"+watchedEvent.getPath());
// 开启循环监听(监听调用此方法,此方法又开启监听)
try {
zk.getChildren("/", true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} /**
* 注册服务器
*/
public void registServer(String hostname) throws KeeperException, InterruptedException {
// 临时有编号的节点,可以重名
String znode = zk.create(parentNode + "/server", hostname.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(hostname+" is online..."+znode);
} /**
* 业务逻辑
*/
public void handleBI(String hostname) throws InterruptedException {
System.out.println(hostname+" start working...");
// 模拟保持不关闭状态
Thread.sleep(Long.MAX_VALUE);
} public static void main(String[] args) throws Exception {
// 获取zk连接
DistributedServer servers = new DistributedServer();
servers.getConn();
// 注册服务器
servers.registServer(args[0]);
// 业务逻辑
servers.handleBI(args[0]);
}
}

  客户端:

package com.zk;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; /**
* 分布式服务器动态感知——客户端
*
* @author zcc ON 2018/1/17
**/
public class DistributedClient {
private static final String coonectString = "192.168.137.128:2181,192.168.137.138:2181,192.168.137.148:2181";
private static final int sessionTimeout = 2000;
private static final String parentNode = "/servers";
// 注意volatile的使用意义(使每个线程都得到最新值)
private volatile List<String> serverList; private ZooKeeper zk = null; /**
* 获得连接
* @throws IOException
*/
public void getConn() throws IOException {
zk = new ZooKeeper(coonectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent watchedEvent) {
try {
// 回调事件重新更新服务器列表并注册监听
getServerList();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} /**
* 业务逻辑
*/
public void handleBI() throws InterruptedException {
System.out.println("client working...");
// 模拟保持不关闭状态
Thread.sleep(Long.MAX_VALUE);
}
public void getServerList() throws KeeperException, InterruptedException {
// 获取服务器子节点信息,并且对父节点监听
List<String> children = zk.getChildren(parentNode, true);
// 用于存放服务器列表的List
List<String> servers = new ArrayList<>();
for (String child : children) {
// 获取数据(这里无需监听,因为连接上了不需要更换连接了)
byte[] data = zk.getData(parentNode + "/" + child, false, null);
servers.add(new String(data));
}
// 更新到成员变量,供业务线程使用
serverList = servers;
// 打印服务器列表
System.out.println(serverList);
} public static void main(String[] args) throws Exception {
// 获取连接
DistributedClient client = new DistributedClient();
client.getConn();
// 获取子节点信息,并监听
client.getServerList();
// 启动业务功能
client.handleBI();
}
}

大数据入门第二天——基础部分之zookeeper(下)的更多相关文章

  1. 大数据入门第二天——基础部分之zookeeper(上)

    一.概述 1.是什么? 根据凡技术必登其官网的原则,我们先去官网瞅一瞅:http://zookeeper.apache.org/ Apache ZooKeeper is an effort to de ...

  2. 大数据入门第一天——基础部分之Linux基础(环境准备与先导知识)

    一.Linux环境安装 1.VM的安装 参考Linux环境搭建随笔:http://www.cnblogs.com/jiangbei/p/7248054.html 2.CentOS的安装 同参考上述随笔 ...

  3. 大数据入门第二十二天——spark(一)入门与安装

    一.概述 1.什么是spark 从官网http://spark.apache.org/可以得知: Apache Spark™ is a fast and general engine for larg ...

  4. 大数据入门第二十五天——elasticsearch入门

    一.概述 推荐路神的ES权威指南翻译:https://es.xiaoleilu.com/010_Intro/00_README.html 官网:https://www.elastic.co/cn/pr ...

  5. 大数据入门第二十二天——spark(二)RDD算子(1)

    一.RDD概述 1.什么是RDD RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的 ...

  6. 大数据入门第二十五天——logstash入门

    一.概述 1.logstash是什么 根据官网介绍: Logstash 是开源的服务器端数据处理管道,能够同时 从多个来源采集数据.转换数据,然后将数据发送到您最喜欢的 “存储库” 中.(我们的存储库 ...

  7. 大数据入门第二十四天——SparkStreaming(一)入门与示例

    一.概述 1.什么是spark streaming Spark Streaming is an extension of the core Spark API that enables scalabl ...

  8. 大数据入门第二十二天——spark(三)自定义分区、排序与查找

    一.自定义分区 1.概述 默认的是Hash的分区策略,这点和Hadoop是类似的,具体的分区介绍,参见:https://blog.csdn.net/high2011/article/details/6 ...

  9. 大数据入门第二十四天——SparkStreaming(二)与flume、kafka整合

    前一篇中数据源采用的是从一个socket中拿数据,有点属于“旁门左道”,正经的是从kafka等消息队列中拿数据! 主要支持的source,由官网得知如下: 获取数据的形式包括推送push和拉取pull ...

随机推荐

  1. ahjesus Axure RP 8.0注册码,亲测可用

    ahjesus Axure RP 8.0注册码 ahjesus Axure RP 8.0注册码 用户名:aaa注册码:2GQrt5XHYY7SBK/4b22Gm4Dh8alaR0/0k3gEN5h7F ...

  2. PHP二维数据排序,二维数据模糊查询

    一.因为项目中的一个报表需要合并三个表的数据,所以分表查询再合并数据,利用PHP数组函数进行排序,搜索.三表合并后的数组结构如下: Array ( [0] => Array ( [history ...

  3. leetCode题解之字符最短路径解法2

    1.题目描述 2.分析 之前使用的大循环再向两边寻找的算法是 O(n^2)复杂度的,可以利用 multimap降低其复杂度. 3.代码 vector<int> shortestToChar ...

  4. Inside Amazon's Kafkaesque "Performance Improvement Plans"

    Amazon CEO and brilliant prick Jeff Bezos seems to have lost his magic touch lately. Investors, empl ...

  5. zabbix日常监控项nginx(五)

    1.开启nginx监控 2.编写脚本来进行数据采集 3.设置用户自定义参数 4.重启zabbix-agent 5.添加item.创建图形.创建触发器 6.创建模板 注:第一次使用可以按需求制定好模板, ...

  6. map filter 的func 放在前面

    map    filter      的func 放在前面 sorted 在后 (    iter..  ,       key=function')

  7. APP案例分析-摩拜单车app

    第二次作业-App案例分析 本次案例分析选用的是 摩拜单车IOS5.7.5版本 测试环境为 IPhone 6s (IOS11.0.1,含有3DTOUCH功能).本次案例分析仅针对APP 而言,并不涉及 ...

  8. 用windows自带的fsutil来创建1G稀疏文件(sparse file)

    fsutils file createnew  a.dat 1073741824 fsutil sparse setflag a.dat fsutil sparse setrange a.dat 0  ...

  9. 从0开始搭建Element项目

    第一步:安装 Node.js/NPM 下载Node.js:https://nodejs.org/zh-cn/download/ 下载安装即可. 第二步:安装 vue-cli 打开 cmd 创建,在命令 ...

  10. laravel 资料

    1.http://maxoffsky.com/maxoffsky-blog/building-a-shop-with-laravel-tutorial-series-announcement/  一篇 ...