Bigdata-Zookeeper集群日志配置详解和清理自定义启动内存

Posted by Yancy on 2017-08-27

Zookeeper集群日志配置详解和清理自定义启动内存

问题:

搭建zookeeper和kafka集群运行大数据处理数据消费,公司dubbo使用zookeeper做服务端的服务发现管理及配置中心,在使用时都出现过由于zk的日志大小过大塞满磁盘的情况 ,遇到了Zookeeper日志问题输出路径的问题, 发现zookeeper设置log4j.properties不能解决日志路径问题, 发现解决方案如下。

zookeeper日志说明

ZooKeeper使用SLF4J(the Simple Logging Facade for Java)作为日志的抽象层,默认使用Log4J来做实际的日志工作。使用2层日志抽象看起来真是够呛,这里简要的说明如何来配置Log4J。尽管Log4J非常灵活且强大,但它也有一些复杂,可以用一整本书来描述它,这里只是简要的介绍一下基本的用法。

Log4J的配置文件名为log4j.properties,从classpath中查找。如果没有找到log4j.properties文件,会输出如下警告信息:

1
2
log4j:WARN No appenders could be found for logger (org.apache.zookeeper.serv ...
log4j:WARN Please initialize the log4j system properly.

它说的是所有后续的日志消息会被丢弃,通常log4j.properties文件会放在conf文件夹,并放在classpath下。
来看看ZooKeeper使用的log4j.properties的主要部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[jollybi@kafka2 conf]$ cat log4j.properties | grep -Pv "^$|^#"
zookeeper.root.logger=INFO, CONSOLE #(1)
zookeeper.console.threshold=INFO
zookeeper.log.dir=.
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=DEBUG
zookeeper.tracelog.dir=.
zookeeper.tracelog.file=zookeeper_trace.log
log4j.rootLogger=${zookeeper.root.logger} #(2)
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender #(3)
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} #(4)
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout #(5)
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender #(6)
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} #(7)
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}
log4j.appender.ROLLINGFILE.MaxFileSize=10MB
log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file}
log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
  • (1) zookeeper.root.logger=INFO, CONSOLE
    第一组设置以zookeeper开头,它们实际上是Java system property,可以被-D形式的命令行参数覆盖。
    第一行配置了日志级别,默认的设置是说在INFO级别以下的日志会被丢弃,并且日志会使用CONSOLE appender输出。你可以指定多个appender,例如如果你想使用CONSOLE appenderROLLINGFILE appender输出日志,那么可以配置zookeeper.loggerINFO,CONSOLE,ROLLINGFILE

  • (2) rootLogger处理所有日志的logger,因为我们没有定义其他logger

  • (3) log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender这一行把CONSOLE appender和实际上处理日志输出的类绑定在一起,这里是ConsoleAppender类。

  • (4) appender也可以过滤日志。这一行将过滤任何在INFO级别之下的日志,因为这是在zookeeper.root.logger设置的threshold

  • (5) appender使用一个布局(layout)类在输出前对日志进行格式化。我们使用pattern layout来记录日志的级别,日期,线程信息和调用位置信息以及消息本身。

  • (6) RollingFileAppender实现了rolling日志文件的功能,而不是持续的写到一个单独的文件或者控制台。如果rootLogger没有关联ROLLINGFILE,则此appender会被忽略。

  • (7) ROLLINGFILE的threshold设置成DEBUG。因为rootLogger过滤了所有在INFO级别之下的日志,没有DEBUG日志会输出到ROLLINGFILE。如果你想要看到DEBUG日志,你必须把zookeeper.root.loggerINFO改成DEBUG

打日志会影响到进程的性能,尤其是在DEBUG级别下。同时日志会提供有价值的信息为诊断错误提供线索。一个平衡性能开销的有效方式是把appender的threshold设成DEBUG,并把rootLogger设成WARN级别,这在一般的情况都适用,一般只需要关注WARNING和它之上的日志。当你需要诊断问题时可以使用JMX动态设置为INFO或DEBUG级别,这样可以更方便定位问题。

快照事物日志,修改日志输出目录

之前出现zookeeper在bin目录下出现了zookeeper.out的日志文件,经分析发现此文件是由于nohup命令打印的控制台日志。

但是,我们在zoo.cfg配置文件中,对日志文件进行了配置(截取部分)

1
2
dataDir=/data/tools/zookeeper-3.4.5/tmp
dataLogDir=/data/tools/zookeeper-3.4.5/tmp/logs

其中,dataDir和dataLogDir是针对数据信息及数据信息日志的位置配置。但是在zookeeper内部集成了log4j.properties(对应配置文件在conf路径下)。

参考log4j配置说明

打开log4j.properties文件,我们会发现有这样的配置,它在说明关于zookeeper本身的一些默认设置,但是可以被系统配置文件所覆盖。那么,在log4j中,root是log4j记录的原始起点,而这部分参数又可以被系统修改,那么系统配置在什么地方呢?

1
2
3
4
5
6
7
8
# Define some default values that can be overridden by system properties
zookeeper.root.logger=INFO, CONSOLE
zookeeper.console.threshold=INFO
zookeeper.log.dir=.
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=DEBUG
zookeeper.tracelog.dir=.
zookeeper.tracelog.file=zookeeper_trace.log

zk日志.out及log4j日志路径配置 :首先修改bin/zkEnv.sh,配置ZOO_LOG_DIR的环境变量,ZOO_LOG_DIR是zookeeper日志输出目录,ZOO_LOG4J_PROP是log4j日志输出的配置:

  • 默认配置:
1
2
3
4
5
6
7
8
9
if [ "x${ZOO_LOG_DIR}" = "x" ]
then
ZOO_LOG_DIR="."
fi
if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
ZOO_LOG4J_PROP="INFO,CONSOLE"
fi
  • 生产环境修改:

在zk目录下面创建logs目录 给予bi组操作权限。

1
2
sudo mkdir /data/tools/zookeeper-3.4.5/logs/
sudo chown -R jollybi:jollybi /data/tools/zookeeper-3.4.5/logs/
1
2
3
4
5
6
7
8
9
if [ "x${ZOO_LOG_DIR}" = "x" ]
then
ZOO_LOG_DIR="$ZOOBINDIR/../logs"
fi
if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
ZOO_LOG4J_PROP="INFO,ROLLINGFILE" //ROLLINGFILE —— 日志轮转,避免单一文件过大
fi

Zk设置定期自动清理日志.

3.4.0开始,zookeeper提供了自动清理snapshot和事务日志的功能,通过配置 autopurge.snapRetainCountautopurge.purgeInterval 这两个参数能够实现定时清理了。这两个参数都是在zoo.cfg中配置的:

  • 在zoo.cfg中配置:
1
2
3
4
5
autopurge.purgeInterval: 24*2
##这个参数指定了清理频率,单位是小时。默认是0,表示不开启自己清理功能。
autopurge.snapRetainCount: 2
##这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个。

配置zookeeper.out的位置及log4j日志输出

1. zookeeper.out由nohup的输出,也就是zookeeperstdout和stdeer输出。

在zkServer.sh中:

1
2
3
4
5
6
7
8
9
if [ ! -w "$ZOO_LOG_DIR" ] ; then
mkdir -p "$ZOO_LOG_DIR"
fi
_ZOO_DAEMON_OUT="$ZOO_LOG_DIR/zookeeper.out" #日志输出文件路径
#nohup日志输出
nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
2.log4j日志输出配置 conf/log4j.properties中:
1
2
3
4
5
6
# Add ROLLINGFILE to rootLogger to get log file output
# Log DEBUG level and above messages to a log file
log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender //日志轮转,DaliyRollingFileAppender —— 按天轮转
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}

轮转前提需要将(1)里bin/zkEnv.sh中的轮转配置好

4.zk事务日志查看

zookeeper的事务日志通过zoo.cfg文件中的dataLogDir配置项配置:

# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper    

查看事务日志方法:
(需要下载slf4j-api-1.6.1.jar包)

1
java -classpath .:slf4j-api-1.6.1.jar:zookeeper-3.4.5.jar org.apache.zookeeper.server.LogFormatter /tmp/zookeeper/version-2/xxx.xxx

怎么自定义zookeeper的启动内存

运行zookeeper时,使用jmap -heap 命令查看内存情况如下:

解决:分配内存文件路径:zookeeper/bin/zkEnv.sh

该文件已经明确说明有独立JVM内存的设置文件,路径是zookeeper/conf/java.env
安装的时候这个路径下没有有java.env文件,需要自己新建一个:

1
2
3
4
5
6
7
8
# vim java.env
#!/bin/sh
export JAVA_HOME=/usr/java/jdk
# heap size MUST be modified according to cluster environment
export JVMFLAGS="-Xms4g -Xmx4g $JVMFLAGS"
对于内存的分配,还是根据项目和机器情况而定。如果内存够用,适当的大点可以提升zk性能。