• 一次Zookeeper 扩展之殇


    一、背景

    基于公司发展硬性需求,生产VM服务器要统一迁移到ZStack 虚拟化服务器。检查自己项目使用的服务器,其中zookeeper集群中招,所以需要进行迁移。

    二、迁移计划

    为了使迁移不对业务产生影响,所以最好是采用扩容 -> 缩容 的方式进行。

    zk

    说明:
    1.原生产集群为VM-1,VM-2,VM-3组成一个3节点的ZK集群;
    2.对该集群扩容,增加至6节点(新增ZS-1,ZS-2,ZS-3),进行数据同步完成;
    3.进行缩容,下掉原先来的三个节点(VM-1,VM-2,VM-3);
    4.替换nginx解析地址。
    
    OK! 目标很明确,过程也很清晰,然后开干。

    三、步骤 (过程已在测试环境验证无问题):

    1. 对新增的三台服务器进行zk环境配置,和老集群配置一样即可,最好使用同一版本(版主使用的是3.4.6);

    2. 对老节点的zoo.cfg 增加新集群的地址(逐一增加),然后对新增加节点逐一重启。

    zk-2

    四、问题

    • ZS-1 启动成功,zkServer.sh status 报错,用zkServer.sh status查看,反馈如下异常:
    [root@localhost bin]# ./zkServer.sh  status
    ZooKeeper JMX enabled by default
    Using config: /usr/zookeeper/zookeeper-3.4.6/bin/../conf/zoo.cfg
    Error contacting service. It is probably not running.
    • 此时查看数据,数据同步正常
    ZS-1 数据同步正常,但是无法查看节点的状态信息;
     
    • 怀疑是因为老节点没有重启的原因;此时去查看原集群节点信息,发现原集群节点状态异常。经排查定位,原集群的状态一直处于异常状态。

    • 初步定位原因可能是原集群的选举存在异常,导致新节点无法正常纳入,继续排查。

    • 恢复集群初始状态,如果集群节点的状态一直没法正常查看。OK 继续定位...

    五、排查过程

    以下方法来自于网络:

    可能有以下几个原因:

    第一、zoo.cfg文件配置:dataLogDir指定的目录未被创建。

    1.zoo.cfg
    [root@SIA-215 conf]# cat zoo.cfg
    ...
    dataDir=/app/zookeeperdata/data
    dataLogDir=/app/zookeeperdata/log
    ...
    
    2.路径
    [root@SIA-215 conf]# cd /app/zookeeperdata/
    [root@SIA-215 zookeeperdata]# ll
    total 8
    drwxr-xr-x 3 root root 4096 Apr 23 19:59 data
    drwxr-xr-x 3 root root 4096 Aug 29  2015 log
     

    经排查 排除该因素。

    第二、myid文件中的整数格式不对,或者与zoo.cfg中的server整数不对应。

    [root@SIA-215 data]# cd /app/zookeeperdata/data
    [root@SIA-215 data]# cat myid 
    2[root@SIA-215 data]# 

    定位排查后排除不是该原因。

    第三、防火墙未关闭。

    使用service iptables stop 关闭防火墙; 使用service iptables status确认; 使用chkconfig iptables off禁用防火墙。

    确认防火墙是关闭的。

    [root@localhost ~]# service iptables status
    iptables: Firewall is not running.
    确认防火墙是关闭的

    第四、端口被占用。

    [root@localhost bin]# netstat -tunlp | grep 2181
    tcp        0      0 :::12181                    :::*                        LISTEN      30035/java          
    tcp        0      0 :::22181                    :::*                        LISTEN      30307/java 
    
    确认端口没有被占用
     

    第五、zoo.cfg文件中主机名出错。

    经测试环境测试,主机名正确,多域名解析也正常,不存在此问题

    第六、hosts文件中,本机的主机名有两个对应,只需保留主机名和ip地址的映射。

    经测试环境测试,主机名正确,多域名解析也正常,不存在此问题 排除。

    第七、zkServer.sh里的nc命令有问题。

     可能是机器上没有安装nc命令,还有种说法是在zkServer.sh里找到这句:
     STAT=`echo stat | nc localhost $(grep clientPort “$ZOOCFG” | sed -e ‘s/.*=//’) 2> /dev/null| grep Mode`
     在nc与localhost之间加上 -q 1 (是数字1而不是字母l)
     
     zookeeper版本是3.4.6,zkServer.sh里根本没有这一句(获取状态的语句没有用nc命令)
    
     # -q is necessary on some versions of linux where nc returns too quickly, and no stat result is output
        clientPortAddress=`grep "^[[:space:]]*clientPortAddress[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
        if ! [ $clientPortAddress ]
        then
            clientPortAddress="localhost"
        fi
        clientPort=`grep "^[[:space:]]*clientPort[^[:alpha:]]" "$ZOOCFG" | sed -e 's/.*=//'`
        STAT=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" 
                 -cp "$CLASSPATH" $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain 
                 $clientPortAddress $clientPort srvr 2> /dev/null    
              | grep Mode`
        if [ "x$STAT" = "x" ]
        then
            echo "Error contacting service. It is probably not running."
            exit 1
        else
            echo $STAT
            exit 0
        fi
        ;;

    六、以下是自己排查的方式:

    目前现象老集群数据同步正常,也能进行leader选举(从日志获取),但是无法查看节点状态,同异常信息;进行集群扩容,数据不能同步。

    解决方法:

    1、尝试进行foreground 模式启动,选择一台非主节点进行重启,可以前台查看启动日志。

    zkserver.sh start-foreground
    
    节点启动正常,无异常输出。

    2、查看shell脚本:分析zkServer.sh。

    • "Error contacting service. It is probably not running." 这块日志出现以下脚本中。
    STAT=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" 
                 -cp "$CLASSPATH" $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain 
                 $clientPortAddress $clientPort srvr 2> /dev/null    
              | grep Mode`
        if [ "x$STAT" = "x" ]
        then
            echo "Error contacting service. It is probably not running."
            exit 1
        else
            echo $STAT
            exit 0
        fi
        ;;
    • 截取其中一部分脚本内容:我们可以初步定为应该是 $STAT 获取存在异常 如果STAT变量为空,则会显示Error contacting service. It is probably not running.: OK,那就分析下这个$STAT到底是什么鬼?
     if [ “x$STAT” = “x” ]
    then
    echo “Error contacting service. It is probably not running.”
    exit 1
    else
    echo $STAT
    exit 0
    fi

    3、尝试用shell的debug模式 看下执行过程:

    • 截取片段执行日志如下 :果然STAT变量确实为空,导致输出Error contacting service. It is probably not running.并且退出。
    ++ grep '^[[:space:]]*clientPort[^[:alpha:]]' /app/zookeeper-3.4.6/bin/../conf/zoo.cfg
    + clientPort=5181
    ++ grep Mode
    ++ /opt/jdk1.8.0_131/bin/java -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp '/app/zookeeper-3.4.6/bin/../build/classes:/app/zookeeper-3.4.6/bin/../build/lib/*.jar:/app/zookeeper-3.4.6/bin/../lib/slf4j-log4j12-1.6.1.jar:/app/zookeeper-3.4.6/bin/../lib/slf4j-api-1.6.1.jar:/app/zookeeper-3.4.6/bin/../lib/netty-3.7.0.Final.jar:/app/zookeeper-3.4.6/bin/../lib/log4j-1.2.16.jar:/app/zookeeper-3.4.6/bin/../lib/jline-0.9.94.jar:/app/zookeeper-3.4.6/bin/../zookeeper-3.4.6.jar:/app/zookeeper-3.4.6/bin/../src/java/lib/*.jar:/app/zookeeper-3.4.6/bin/../conf:.:/opt/jdk1.8.0_131/lib/dt.jar:/opt/jdk1.8.0_131/lib/tools.jar' org.apache.zookeeper.client.FourLetterWordMain localhost 5181 srvr
    + STAT=
    + ‘[‘ x = x ‘]’
    + echo ‘Error contacting service. It is probably not running.’
    Error contacting service. It is probably not running.
    + exit 1

    4、修改shell脚本:分析zkServer.sh 在脚本总增加输出STAT 内容,这次我们不进行过滤。

    STAT1=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" 
                 -cp "$CLASSPATH" $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain 
                 $clientPortAddress $clientPort srvr 2> test.log  `
    
    echo "$STAT1"
     
    • 最好的方式是copy一个新脚本,以免污染原本的脚本。我是这么做的;然后运行该脚本。
    [root@localhost bin]# ./zkServer.sh  status
    ZooKeeper JMX enabled by default
    Using config: /usr/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
    Error contacting service. It is probably not running.
    • 然后查看生成的test.log 文件:果然存在异常内容。
    in thread “main” java.lang.NumberFormatException: For input string: “2181
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:492)
    at java.lang.Integer.parseInt(Integer.java:527)
    at org.apache.zookeeper.client.FourLetterWordMain.main(FourLetterWordMain.java:76)
    • 从日志信息来看,提示说2181这个端口号造成的。 不是一个合法的数字。

    zkServer.sh里有这么一句:

    clientPort=`grep “^[[:space:]]*clientPort[^[:alpha:]]” “$ZOOCFG” | sed -e ‘s/.*=//’`
    grep “^[[:space:]]*clientPort[^[:alpha:]]” “$ZOOCFG” | sed -e ‘s/.*=//’在执行过程中,实际命令如下:
    grep ‘^[[:space:]]*clientPort[^[:alpha:]]’ /app/zookeeper-3.4.6/bin/../conf/zoo.cfg | sed -e ‘s/.*=//
    • 最终可以基本确认配置文件存在问题。

    • 替换配置文件:重启 问题解决。

    • 存在原因可能是编辑zoo.cfg 编码格式等等引起文件内容解析异常。

    作者: 毛正卫

    拓展阅读:宜信敏捷数据中台建设实践|分享实录

  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/yixinjishu/p/10942808.html
Copyright © 2020-2023  润新知