Zookeeper 之学习笔记。

一、ZooKeeper 概述

1.1 由来

下面这段内容摘自《从 Paxos 到 ZooKeeper 》第四章第一节的某段内容,推荐大家阅读一下:

Zookeeper 最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。

所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。

关于“ZooKeeper”这个项目的名字,其实也有一段趣闻。在立项初期,考虑到之前内部很多项目都是使用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。

时任研究院的首席科学家 Raghu Ramakrishnan 开玩笑地说:“在这样下去,我们这儿就变成动物园了!”

此话一出,大家纷纷表示就叫动物园管理员吧,因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了。

而 Zookeeper 正好要用来进行分布式环境的协调,于是,Zookeeper 的名字也就由此诞生了。

1.2 概述

Zookeeper是一个开源的分布式的,为分布式应用 提供协调服务 的Apache项目。
Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

原语: 操作系统或计算机网络用语范畴。它是由若干条指令组成的,用于完成一定功能的一个过程。具有不可分割性,即原语的执行必须是连续的,在执行过程中不允许被中断。

ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

ZooKeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。

服务生产者将自己提供的服务注册到 ZooKeeper 中心,服务的消费者在进行服务调用的时候先到 ZooKeeper 中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。

1.3 特点

1)Zookeeper:一个领导者(leader),多个跟随者(follower)组成的集群。
在这里插入图片描述
2)主要是监听机制(心跳检测)+文件系统 ((K,V)结构存储)
3)Leader负责进行投票的发起和决议,更新系统状态。
4)Follower用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票。
5)集群中奇数台服务器只要有半数以上节点存活,Zookeeper集群就能正常服务。
6)全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的。
7)更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
8)数据更新原子性,一次数据更新要么成功,要么失败。
9)实时性,在一定时间范围内,client能读到最新数据。

1.4 数据模型

ZooKeeper 允许分布式进程通过共享的层次结构命名空间进行相互协调,这与标准文件系统类似。

名称空间由 ZooKeeper 中的数据寄存器组成,称为 Znode,这些类似于文件和目录。整体上可以看作是一棵树,每个节点称做一个ZNode。每一个ZNode默认能够存储1MB的元数据,每个ZNode都可以通过其路径唯一标识。
数据模型
与为存储设计的典型文件系统不同,ZooKeeper 数据保存在内存中,这意味着 ZooKeeper 可以实现高吞吐量和低延迟。

1.5 应用场景

提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。

1.5.1 统一命名服务

统一命名服务

1.5.2 统一配置管理

1、分布式环境下,配置文件管理和同步是一个常见问题。
(1) 一个集群中,所有节点的配置信息是一致的,比如hadoop集群。
(2) 对配置文件修改后,希望能够快速同步到各个节点上。

2、配置管理可交由ZK实现
(1)可配置信息写入ZK上的一个Znode
(2)各个节点监听这个ZNode
(3)一旦Znode中的数据被修改,ZK将通知各个节点
在这里插入图片描述

1.5.3 统一集群管理

集群管理结构图如下所示。
1、 分布式环境中,实时掌握每个节点的状态是必要的。
(1) 可根据节点实时做出一些调整

2、 可交由Zk实现
(1) 可将节点信息写入ZK上的一个ZNode
(2) 监听这个Znode可获取它的实时状态变化

3、 典型应用
(1) HBase中Master状态监控与选举
在这里插入图片描述
1.4.4 服务器节点动态上下线
在这里插入图片描述
1.4.5 软负载均衡
在这里插入图片描述

二、 Zookeeper内部原理

2.1 选举机制

Server ID: myid(权重越大)
Zxid:数据ID(先一数据低进行选择)

1)半数机制(Paxos 协议):集群中半数以上机器存活,集群可用。所以zookeeper适合装在奇数台机器上。
2)Zookeeper虽然在配置文件中并没有指定master和slave。但是,zookeeper工作时,是有一个节点为leader,其他则为follower,Leader是通过内部的选举机制临时产生的。
3)以一个简单的例子来说明整个选举的过程。
假设有五台服务器组成的zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动,来看看会发生什么。

(1)服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是LOOKING状态。
(2)服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1、2还是继续保持LOOKING状态。
(3)服务器3启动,根据前面的理论分析,服务器3成为服务器1、2、3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader。
(4)服务器4启动,根据前面的分析,理论上服务器4应该是服务器1、2、3、4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了。
(5)服务器5启动,同4一样当小弟。

2.2 节点类型

1)Znode有两种类型:
短暂(ephemeral):客户端和服务器端断开连接后,创建的节点自己删除
持久(persistent):客户端和服务器端断开连接后,创建的节点不删除
2)Znode有四种形式的目录节点(默认是persistent )
(1)持久化目录节点(PERSISTENT)(小写:persistent)
客户端与zookeeper断开连接后,该节点依旧存在。
(2)持久化顺序编号目录节点(PERSISTENT_SEQUENTIAL)
(小写:persistent_sequential)
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
(3)临时目录节点(EPHEMERAL)(ephemeral)
客户端与zookeeper断开连接后,该节点被删除。
(4)临时顺序编号目录节点(EPHEMERAL_SEQUENTIAL)(ephemeral_sequential)
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
在这里插入图片描述

3)创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
4)在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序

2.3 stat结构体

1)czxid- 引起这个znode创建的zxid,创建节点的事务的zxid
每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。
事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
2)ctime - znode被创建的毫秒数(从1970年开始)
3)mzxid - znode最后更新的zxid
4)mtime - znode最后修改的毫秒数(从1970年开始)
5)pZxid-znode最后更新的子节点zxid
6)cversion - znode子节点变化号,znode子节点修改次数
7)dataversion - znode数据变化号
8)aclVersion - znode访问控制列表的变化号
9)ephemeralOwner- 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
10)dataLength- znode的数据长度
11)numChildren - znode子节点数量

2.4 监听器原理

1、 监听原理详解:

  1. 首先要有一个main()线程
  2. 在main线程中创建ZK客户端,这是会创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener)
  3. 通过connect线程将注册的监听事件发送给ZK
  4. 在ZK的注册监听器列表中将注册的监听事件添加到列表中
  5. ZK监听到有数据或路径发生变化时,就会将这个消息发送给listener线程
  6. Listener线程内部调用process()方法

2、 常见的监听

  1. 监听节点数据的变化
    1. Get path [watch]
  2. 监听子节点增减的变化
    1. Ls path [watch]

在这里插入图片描述
3.5 写数据流程
在这里插入图片描述

读是局部性的,即client只需要从与它相连的server上读取数据即可;而client有写请求的话,与之相连的server会通知leader,然后leader会把写操作分发给所有server。所以定要比读慢很多。

三、 Zookeeper集群部署与安装

3.1 下载地址

1)官网首页:https://zookeeper.apache.org/
2)下载截图:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

3.2 分布式安装部署

1)安装前准备:

(1)安装jdk
(2)上传zookeeper到linux系统下
(3)修改tar包权限

[root@bigdata01 software]$ ll
total 455748
-rw-r--r-- 1 root root 246123562 Nov 19  2019 hadoop-2.8.4.tar.gz
-rw-r--r-- 1 root root 185515842 Nov 17  2019 jdk-8u144-linux-x64.tar.gz
-rw-r--r-- 1 root root  35042811 Dec  1  2019 zookeeper-3.4.10.tar.gz
[root@bigdata01 software]$ chmod u+x zookeeper-3.4.10.tar.gz
[root@bigdata01 software]$ ll
total 455748
-rw-r--r-- 1 root root 246123562 Nov 19  2019 hadoop-2.8.4.tar.gz
-rw-r--r-- 1 root root 185515842 Nov 17  2019 jdk-8u144-linux-x64.tar.gz
-rwxr--r-- 1 root root  35042811 Dec  1  2019 zookeeper-3.4.10.tar.gz

(4)解压到指定目录

[root@bigdata01 software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/

(5)配置环境变量

[root@bigdata01 software]$ vi /etc/profile
# zk_HOME
export zk_HOME=/opt/module/zookeeper-3.4.10
export PATH=$PATH:$ zk_HOME E/bin

初始化:source /etc/profile

2)配置修改步骤

(1)将/opt/module/zookeeper-3.4.10/conf这个路径下的zoo_sample.cfg修改为zoo.cfg;

[root@bigdata01 software]# cd /opt/module/zookeeper-3.4.10/conf
[root@bigdata01 conf]# mv zoo_sample.cfg  zoo.cfg

(2)进入vi zoo.cfg文件,配置zoo.cfg文件
  1. 修改dataDir路径为:dataDir=/opt/module/zookeeper-3.4.10/zkData
    在这里插入图片描述

2. 末尾增加如下配置

#增加如下配置
#######################cluster##########################
server.1=bigdata01:2888:3888
server.2=bigdata02:2888:3888
server.3=bigdata03:2888:3888
在这里插入图片描述

配置参数解读: Server.A=B:C:D。
        A 是一个数字,表示这个是第几号服务器;
        B 是这个服务器的ip地址;
        C 是这个服务器与集群中的Leader服务器交换信息的端口;
        D 是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
        集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。

  1. 在/opt/module/zookeeper-3.4.10/这个目录中创建zkData文件夹,并在zkData目录中创建myid文件,在myid文件中添加与server对应的编号:如1。
[root@bigdata01 zookeeper-3.4.10]# mkdir -p /opt/module/zookeeper-3.4.10/zkData
[root@bigdata01 zookeeper-3.4.10]# cd /opt/module/zookeeper-3.4.10/zkData
[root@bigdata01 zkData]#touch myid
[root@bigdata01 zkData]#echo '1'>>myid
[root@bigdata01 zkData]# cat myid
1
3)其他服务器集群搭建
  1. 拷贝配置好的zookeeper文件拷贝发送到到其他服务器上
[root@bigdata01 module]#scp -r zookeeper-3.4.10/ root@bigdata02:/opt/module/
[root@bigdata01 module]#scp -r zookeeper-3.4.10/ root@bigdata03:/opt/module/
  1. 修改myid
    在bigdata02中修改myid的值为2
[root@bigdata02 zkData]# echo '2'>myid

在bigdata03中修改myid的值为3

[root@bigdata03 zkData]# echo '3'>myid
  1. zookeeper集群搭建完成。

三、 Zookeeper集群操作

1)启动集群:

1、分别启动zookeeper
[root@bigdata01 zookeeper-3.4.10]# zkServer.sh start
[root@bigdata02 zookeeper-3.4.10]# zkServer.sh start
[root@bigdata03 zookeeper-3.4.10]# zkServer.sh start
(5)查看状态
[root@bigdata01 zookeeper-3.4.10]# zkServer.sh statu在这里插入图片描述
[root@bigdata02 zookeeper-3.4.10]# zkServer.sh status
在这里插入图片描述
[root@bigdata03 zookeeper-3.4.5]# zkServer.sh status
在这里插入图片描述

2) 客户端命令行操作

2.1)启动客户端
[itstar@bigdata01 zookeeper-3.4.10]$ zkCli.sh
2.2)显示所有操作命令
[zk: localhost:2181(CONNECTED) 1] help

命令基本语法功能描述
help显示所有操作命令
ls path [watch]使用 ls 命令来查看当前znode中所包含的内容
create普通创建(永久节点)
-s 含有序列
-e 临时(重启或者超时消失)
get path [watch]获得节点的值
set设置节点的具体值
stat查看节点状态
delete删除节点
rmr递归删除节点

2.3)查看当前znode中所包含的内容

[zk: localhost:2181(CONNECTED) 0] ls /
在这里插入图片描述

2.4)查看当前节点数据并能看到更新次数等数据

[zk: localhost:2181(CONNECTED) 1] ls2 /
在这里插入图片描述

2.5)创建普通节点
[zk: localhost:2181(CONNECTED) 6] create /app “hello app”
[zk: localhost:2181(CONNECTED) 7] create /app/server101 “192.168.1.101”
在这里插入图片描述
2.6)获得节点的值
[zk: localhost:2181(CONNECTED) 9] get /app
[zk: localhost:2181(CONNECTED) 10] get /app/server101
在这里插入图片描述
2.7)创建短暂节点
[zk: localhost:2181(CONNECTED) 9] create -e /app-emphemeral 8888
(1)在当前客户端(zkCli.sh)是能查看到的
[zk: localhost:2181(CONNECTED) 10] ls /
[app1, app-emphemeral, zookeeper]
(2)退出当前客户端(quit)然后再重启客户端
[zk: localhost:2181(CONNECTED) 12] quit
[itstar@bigdata113 zookeeper-3.4.10]$ bin/zkCli.sh
(3)再次查看根目录下短暂节点已经删除
[zk: localhost:2181(CONNECTED) 0] ls /
[app, zookeeper]
2.8)创建带序号的节点
(1)先创建一个普通的根节点app2
[zk: localhost:2181(CONNECTED) 11] create /app1 “app1”
(2)创建带序号的节点
[zk: localhost:2181(CONNECTED) 13] create -s /app1/aa 888
Created /app1/aa0000000000
[zk: localhost:2181(CONNECTED) 14] create -s /app1/bb 888
Created /app1b0000000001
[zk: localhost:2181(CONNECTED) 15] create -s /app1/cc 888
Created /app1/cc0000000002
如果原节点下有1个节点,则再排序时从1开始,以此类推。
[zk: localhost:2181(CONNECTED) 16] create -s /app1/aa 888
Created /app1/aa0000000001
2.9)修改节点数据值
[zk: localhost:2181(CONNECTED) 2] set /app 999
2.10)节点的值变化监听(生效一次)
(1)在03主机上注册监听/app节点数据变化
[zk: localhost:2181(CONNECTED) 26] get /app watch
(2)在01主机上修改/app节点的数据
[zk: localhost:2181(CONNECTED) 5] set /app 777
(3)观察04主机收到数据变化的监听
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/app
2.11)节点的子节点变化监听(路径变化)
(1)在03主机上注册监听/app节点的子节点变化
[zk: localhost:2181(CONNECTED) 2] ls /app watch
[server101]
(2)在01主机/app/server101/01节点上创建子节点
[zk: localhost:2181(CONNECTED) 3] create /app/server101/01 111
Created /app/server101/01
在这里插入图片描述
(3)观察03主机收到子节点变化的监听(无变化)
(4)在01主机客户端/app创建子节点server103/节点上创建子节点
[zk: localhost:2181(CONNECTED) 3] create /app/server103 111
Created /app/server103/
(5)观察03主机收到子节点变化的监听(报警)
在这里插入图片描述
总结:

监听只对当前节点有效,对父节点、子节点都无效,且监听只能生效一次

2.12)查看节点状态
[zk: localhost:2181(CONNECTED) 26] stat /app
在这里插入图片描述
2.12)删除节点
[zk: localhost:2181(CONNECTED) 22] delete /app/server 101
[zk: localhost:2181(CONNECTED) 22] delete /app/server 103
在这里插入图片描述
delete 只能删除无子节点的节点。

2.13)递归删除节点
[zk: localhost:2181(CONNECTED) 28] rmr /app
在这里插入图片描述

四、 API应用

4.1 IDEA环境搭建

创建一个工程
1)加入 log4j.properties (内容如下):

log4j.rootLogger=INFO, stdout  
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
log4j.appender.logfile=org.apache.log4j.FileAppender  
log4j.appender.logfile.File=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n  

2)Pom.xml:

    <dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
</dependencies>

4.2 创建ZooKeeper客户端

private static String connectString = "bigdata111:2181,bigdata112:2181,bigdata113:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zkClient = null;

	@Before
	public void init() throws Exception {

	zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			@Override
			public void process(WatchedEvent event) {
				// 收到事件通知后的回调函数(用户的业务逻辑)
				System.out.println(event.getType() + "--" + event.getPath());

				// 再次启动监听
				try {
					zkClient.getChildren("/", true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

4.3 创建子节点

// 创建子节点
	@Test
	public void create() throws Exception {
		// 数据的增删改查
		// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
		String nodeCreated = zkClient.create("/eclipse", "hello zk".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
	}

4.4 获取子节点并监听

// 获取子节点
	@Test
	public void getChildren() throws Exception {
		List<String> children = zkClient.getChildren("/", true);

		for (String child : children) {
			System.out.println(child);
		}

		// 延时阻塞
		Thread.sleep(Long.MAX_VALUE);
	}

4.5 判断znode是否存在

// 判断znode是否存在
	@Test
	public void exist() throws Exception {
		Stat stat = zkClient.exists("/eclipse", false);

		System.out.println(stat == null ? "not exist" : "exist");
	}

五、备注

5.1 运行日志zookeeper.out输出路径

搭建zookeeper集群完成时,每次启动Zookeeper集群,会在当前目录产生Zookeeper.out日志文件(即Zookeeper中运行日志 zookeeper.out 文件的输出路径默认为启动脚本的当前路径),导致到处产生.out文件,而且Zookeeper集群启动失败时总是不记得输出日志在哪儿,不便于查找错误原因,因此很有必要设置固定路径来保存运行日志。

把运行日志文件 zookeeper.out 输出路径指定为$ZOOKEEPER_HOME/zkLogs/runtime/路径下

修改方法:

  1. 修改 $ZOOKEEPER_HOME/bin/zkEnv.sh
  • $ ZOOBINDIR/…/logs/runtime,其中$ZOOBINDIR变量是此脚本开头获取的Zookeeper的bin路径,我们直接以此来定位自己的日志路径即可。具体如下:
# 修改前
 54 if [ "x${ZOO_LOG_DIR}" = "x" ]
 55 then
 56     ZOO_LOG_DIR="."
 57 fi

# 修改后
 54 if [ "x${ZOO_LOG_DIR}" = "x" ]
 55 then
 56     #ZOO_LOG_DIR="."
 57     #自定义启动客户端日志文件输出路径,$ZOOBINDIR是bin目录
 58     ZOO_LOG_DIR="$ZOOBINDIR/../zkLogs/runtime"
 59 fi
  • 这样在每次使用zkSever的时候,都能将运行日志 zookeeper.out
    输出到指定路径下,但这样配置有个问题,就是每次运行Zookeeper时,此日志都会被覆盖,而不是append到文件中,故每次运行结束后只会保存有本次运行日志,若单次运行时间很长也会导致日志文件也很大。


  • 在之前的配置中,我们只是实现了保存本次Zookeeper运行日志在指定路径下,这次我们通过配置$ZOOKEEPER_HOME/conf/log4j.properties来使用log4j日志框架将Zookeeper每次的运行日志都保存到指定路径下。

  1. 修改$ZOOKEEPER_HOME/conf/log4j.properties文件
# 修改前
  2  zookeeper.root.logger=INFO, CONSOLE
...
  5  zookeeper.log.dir=.
...
 45  #log4j.appender.ROLLINGFILE.MaxBackupIndex=10

# 修改后
  3  zookeeper.root.logger=INFO, CONSOLE, ROLLINGFILE
...
  6 zookeeper.log.dir=/opt/module/zookeeper-3.4.10/zkLogs/runtime
...
 46 #设置最大日志数量 add by 20210306
 47 log4j.appender.ROLLINGFILE.MaxBackupIndex=5

其中参数zookeeper.root.logger是设置日志优先级和打印方式,默认为控制台打印CONSOLE,而在zkServer.sh中会启动后台命令,将控制台输出的日志输出重定向到 zookeeper.out 文件中。修改后添加了滚动产生文件输出方式ROLLINGFILE;

通过参数zookeeper.log.dir设置日志文件 zookeeper.log 的存储路径,这里直接采用绝对路径,相对路径可能不识别;

通过参数log4j.appender.ROLLINGFILE.MaxBackupIndex设置最大日志数量,每个日志文件大小最大默认为10MB,以此文件大小进行分割,默认日志文件名为 zookeeper.log,其中所有参数都可以自定义修改。其余参数不再赘述。

  1. 修改$ZOOKEEPER_HOME/bin/zkEnv.sh
  • 将其中的ZOO_LOG4J_PROP设置成与log4j配置文件中相同,避免参数覆盖。具体如下:
    #修改前
 61 if [ "x${ZOO_LOG4J_PROP}" = "x" ]
 62 then
 63     ZOO_LOG4J_PROP="INFO,CONSOLE"
 64 fi

    #修改后
 61 if [ "x${ZOO_LOG4J_PROP}" = "x" ]
 62 then
 63	   #ZOO_LOG4J_PROP="INFO,CONSOLE"
 64    #自定义运行日志信息输出方式,增加了滚动输出的方式,初始只有控制台输出
 65    ZOO_LOG4J_PROP="INFO,CONSOLE,ROLLINGFILE"
 66 fi

  1. 修改$ZOOKEEPER_HOME/bin/zkServer.sh
  • 修改原始输出逻辑,不再将本次运行日志信息所有输出到 zookeeper.out 中,而是使用log4j框架输出到zookeeper.log 中,便于管理。而 zookeeper.out 只用于输出标准错误。具体如下所示:
# 修改前
  141     nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
  142     -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
# 修改后
  143     # 将原始指令注释,设置新的输出逻辑,只讲标准错误输出到zookeeper.out中.修改后:
  144     nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
  145     -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" 2> "$_ZOO_DAEMON_OUT" 1> /dev/null &

总结
这样就能保证历史运行日志都能输出到指定文件夹中,并且不会因为运行日志文件堆积造成负载点爆炸。而标准错误都会输出到 zookeeper.out 文件中,和运行日志放置在同一文件夹中。当需要查看脚本命令错误时,可以查看 zookeeper.out 文件,当需要查看程序错误时就查看 zookeeper.log 运行日志文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值