7.Zookeeper指标数据异常问题分析

  • ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。
    • 它是一个为分布式应用提供一致性服务的软件,提供的功能包括:
      • 配置维护
      • 域名服务
      • 分布式同步
      • 组服务等。

7.1 指标数据异常问题描述

  • 从CDH管理平台,进入Zookeeper管理界面,Zookeeper的平均请求延迟、最小请求延迟、最大请求延迟指标趋势图维持不变,指标数据异常。
    • 从CDH平台,进入Zookeeper管理页面,查看Zookeeper各服务器状态,页面如下:


    • 查看如下指标
      • 平均请求延迟、最小请求延迟、最大请求延迟三个指标维持不变,指标异常。

7.2 指标数据异常问题分析

7.2.1 指标数据异常来源

  • 该指标是CDH通过ZookeeperJMX方式获取
    • 通过命令方式获取Zookeeper指标信息
[root@ip-172-31-10-61 ~]# echo mntr |nc 172.31.10.61 2181
zk_version       3.4.5-cdh5.10.0--1, built on 01/20/2017 20:10 GMT
zk_avg_latency  0
zk_max_latency  10
zk_min_latency  0
zk_packets_received      30569
zk_packets_sent 31521
zk_num_alive_connections        7
zk_outstanding_requests 0
zk_server_state follower
zk_znode_count  62
zk_watch_count  14
zk_ephemerals_count      9
zk_approximate_data_size        3049
zk_open_file_descriptor_count   43
zk_max_file_descriptor_count    32768
  • 通过以上分析可以判断指标数据非CDH计算得来,而是Zookeeper计算,排除CM问题

7.2.2 分析Zookeeper源码

  • 命令行调用Zookeeper监控指标代码片段(MonitorCommand.java)
public void  commandRun() {
        if  (!isZKServerRunning()) {
            pw.println(ZK_NOT_SERVING);
            return;
        }
        ZKDatabase zkdb = zkServer.getZKDatabase();
        ServerStats stats = zkServer.serverStats();
        print("version",  Version.getFullVersion());
        print("avg_latency", stats.getAvgLatency());
        print("max_latency", stats.getMaxLatency());
        print("min_latency", stats.getMinLatency());

        print("packets_received", stats.getPacketsReceived());
        print("packets_sent", stats.getPacketsSent());
        print("num_alive_connections", stats.getNumAliveClientConnections());

        print("outstanding_requests", stats.getOutstandingRequests());

        print("server_state", stats.getServerState());
        print("znode_count", zkdb.getNodeCount());

        print("watch_count", zkdb.getDataTree().getWatchCount());
        print("ephemerals_count", zkdb.getDataTree().getEphemeralsCount());
        print("approximate_data_size", zkdb.getDataTree().approximateDataSize());

        OSMXBean osMbean = new  OSMXBean();
        if (osMbean != null  && osMbean.getUnix()  == true) {
            print("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
            print("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
        }

        if (stats.getServerState().equals("leader")) {
            Leader leader =  ((LeaderZooKeeperServer)zkServer).getLeader();

            print("followers", leader.getLearners().size());
            print("synced_followers", leader.getForwardingFollowers().size());
            print("pending_syncs", leader.getNumPendingSyncs());
        }
}
  • 通过查看源码,指标数据是通过ServerStats获取“请求延迟”指标
  • 分析ServerStats代码,代码片段(ServerStats.java)
//更新minLatency、maxLatency、count、totalLatency数据
synchronizedvoid  updateLatency(longrequestCreateTime) {
        longlatency = Time.currentElapsedTime()  - requestCreateTime;
        totalLatency += latency;
        count++;
        if (latency < minLatency) {
            minLatency = latency;
        }
        if (latency > maxLatency)  {
            maxLatency = latency;
        }
}
//获取avgLatency指标
synchronizedpubliclong getAvgLatency() {
    if (count != 0) {
        returntotalLatency / count;
    }
    return 0;
}
  • ServerStats只提供了updateLatency方法来更新maxLatency和minLatency指标。
  • 调用更新ServerStats方法代码片段如下:(FinalRequestProcessor.java)
case OpCode.ping: {
                zks.serverStats().updateLatency(request.createTime);

                lastOp = "PING";
                cnxn.updateStatsForResponse(request.cxid, request.zxid, lastOp,
                        request.createTime, Time.currentElapsedTime());

                cnxn.sendResponse(new  ReplyHeader(-2,
                        zks.getZKDatabase().getDataTreeLastProcessedZxid(),  0), null, "response");
                return;
            }
            case OpCode.createSession: {
                zks.serverStats().updateLatency(request.createTime);

                lastOp = "SESS";
                cnxn.updateStatsForResponse(request.cxid, request.zxid, lastOp,
                        request.createTime, Time.currentElapsedTime());

                zks.finishSessionInit(request.cnxn, true);
                return;
            }

7.2.3 异常数据指标分析

  • 通过分析代码,maxLatency和minLatency指标数据在Zookeeper服务器启动记录每次Request的指标数据;
  • 在获取Zookeeper服务器的的maxLatency和minLatency指标记录服务器所有请求中最大请求延迟和最小请求延迟;
    • 最大请求延迟指标
      • Zookeeper服务器1,在通过A请求更新ServerStats的maxLatency的指标值 为100ms,在之后所有请求均未超过maxLatency为100ms的值。
      • CDH平台每次获取Zookeeper服务器1的maxLatency指标时均为100ms,因此导致文章开头CDH平台Zookeeper的maxLatency指标维持不变“异常”。
    • 最小请求延迟指标
      • Zookeeper服务器1,在通过A请求后更新ServerStats的minLatency的指标值为0ms,在之后所有请求均未小于minLatency为0ms的值。
      • CDH平台每次获取Zookeeper服务器1的minLatency指标时均为0ms,因此导致文章开头CDH平台Zookeeper的minLatency指标为0ms维持不变的“异常”。
    • 平均请求延迟指标
      • Zookeeper服务器1累计所有请求的延迟时间(totalLatency),累计总共请求次数(count),通过totalLatency/count获取avgLatency指标。
      • 至于avgLatency指标持续维持为0ms,由于totalLatency <count导致。
  • 由此推断多次请求Latency的延迟为0ms。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容