0006-Zookeeper指标分析

Fayson的github: https://github.com/fayson/cdhproject
推荐关注微信公众号:“Hadoop实操”,ID:gh_c4c535955d0f,或者扫描文末二维码。

1. 问题描述

通过CDH管理平台,进入Zookeeper管理界面,Zookeeper的平均请求延迟、最小请求延迟、最大请求延迟指标趋势图维持不变,指标数据异常。

2.问题复现

  • 登录CDH平台,进入Zookeeper管理页面,查看Zookeeper各服务器状态,页面如下:

    《0006-Zookeeper指标分析》

  • 查看如下指标

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

《0006-Zookeeper指标分析》

《0006-Zookeeper指标分析》

《0006-Zookeeper指标分析》

3.问题分析

3.1.指标来源

  • 该指标是CDH通过ZookeeperJMX方式获取,具体参考Zookeeper官网
http://zookeeper.apache.org/doc/r3.5.3-beta/zookeeperJMX.html#ch_jmx
  • 通过命令方式获取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问题;

3.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数据
synchronized void updateLatency(long requestCreateTime) {
        long latency = Time.currentElapsedTime() - requestCreateTime;
        totalLatency += latency;
        count++;
        if (latency < minLatency) {
            minLatency = latency;
        }
        if (latency > maxLatency) {
            maxLatency = latency;
        }
}
//获取avgLatency指标
synchronized public long getAvgLatency() {
    if (count != 0) {
        return totalLatency / 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;
            }

3.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。

为天地立心,为生民立命,为往圣继绝学,为万世开太平。
推荐关注Hadoop实操,第一时间,分享更多Hadoop干货,欢迎转发和分享。

《0006-Zookeeper指标分析》

原创文章,欢迎转载,转载请注明:转载自微信公众号Hadoop实操

《0006-Zookeeper指标分析》

    原文作者:Hadoop实操
    原文地址: https://www.jianshu.com/p/0aab51d4519e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞