大数据集群资源监控(一)—— IDC集群相关指标获取

背景:
公司自建IDC机房,基于IDC机房构建大数据集群;需要对集群资源进行监控,集群采用的是CDH集群,采集主要分两块进行:

  • HDFS和YARN相关的指标进行采集
  • IDC机器自身的指标进行采集

注意: 也许有人会有疑惑,CM界面已经提供了监控的图表,为什么还需要自己进行展示。原因在于,这些信息需要集成到内部的数据平台上面去,做成对应的数据报表,可视化的方式展示在自己的数据平台上

实现思路大致可以分为两种:

  • 使用CM所提供的Java API去获取
  • 使用CM提供的REST API去获取

其实两者本质上是一样的,CM所提供的Java API也是按照REST API那套来实现的,两者是保持一致的

核心代码如下:

public class IdcHostResource {
    private static final Logger LOGGER = LoggerFactory.getLogger(IdcHostResource.class);

    static RootResourceV18 apiRoot;

    // TODO... 写死了,需要改进
    static {
        apiRoot = new ClouderaManagerClientBuilder()
                .withHost("cm ip")
                .withPort(7180)
                .withUsernamePassword("user", "passwd")
                .build()
                .getRootV18();
    }

    /**
     * 固定获取Host的基本资源信息
     */
    public static List<IdcHostBasicInfo> getAllHostResource() {
        List<IdcHostBasicInfo> hosts = new ArrayList<IdcHostBasicInfo>();
        HostsResourceV10 hostsResourceV10 = apiRoot.getHostsResource();
        List<ApiHost> hostLists = hostsResourceV10.readHosts(DataView.SUMMARY).getHosts();
        LOGGER.info("Total" + hostLists.size() + "Host");
        for (ApiHost hostList : hostLists) {
            IdcHostBasicInfo host = formatHost(hostsResourceV10.readHost(hostList.getHostId()));
            LOGGER.info("Host Name:" + host.getHostName());
            LOGGER.info("Host Health Summary:" + host.gethostHealthSummary());
            LOGGER.info("Host Physical Memory:" + host.getTotalPhysMemBytes());
            hosts.add(host);
        }
        return hosts;
    }

    public static IdcHostBasicInfo formatHost(ApiHost apiHost) {
        IdcHostBasicInfo idcHostBasicInfo = new IdcHostBasicInfo();
        idcHostBasicInfo.sethostHealthSummary(apiHost.getHealthSummary().toString());
        idcHostBasicInfo.setHostName(apiHost.getHostname());
        idcHostBasicInfo.setTotalPhysMemBytes(apiHost.getTotalPhysMemBytes());
        return idcHostBasicInfo;
    }

    /**
     * 通过tsquery来动态获取对应的metrics info
     *
     * @param query
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<IdcMetricInfo> getHostMetrics(String query, String startTime, String endTime) throws ParseException {
        TimeSeriesResourceV11 timeSeriesResourceV11 = apiRoot.getTimeSeriesResource();
        ApiTimeSeriesResponseList responseList = timeSeriesResourceV11.queryTimeSeries(query, startTime, endTime);
        List<ApiTimeSeriesResponse> apiTimeSeriesResponseList = responseList.getResponses();
        List<IdcMetricInfo> metrics = formatApiTimeSeriesResponseList(apiTimeSeriesResponseList);
        return metrics;
    }

    public static List<IdcMetricInfo> formatApiTimeSeriesResponseList(List<ApiTimeSeriesResponse> apiTimeSeriesResponseList) throws ParseException {
        List<IdcMetricInfo> metrics = new ArrayList<IdcMetricInfo>();
        DateUtils dateUtils = new DateUtils();
        for (ApiTimeSeriesResponse apiTimeSeriesResponse : apiTimeSeriesResponseList) {
            List<MetricData> dataList = new ArrayList<MetricData>();
            List<ApiTimeSeries> apiTimeSeriesResponseLists = apiTimeSeriesResponse.getTimeSeries();
            for (ApiTimeSeries apiTimeSeries : apiTimeSeriesResponseLists) {
                LOGGER.info("query sql is: " + apiTimeSeries.getMetadata().getExpression());
                IdcMetricInfo metric = new IdcMetricInfo();
                metric.setMetricName(apiTimeSeries.getMetadata().getMetricName());
                metric.setEntityName(apiTimeSeries.getMetadata().getEntityName());
                metric.setStartTime(apiTimeSeries.getMetadata().getStartTime().toString());
                metric.setEndTime(apiTimeSeries.getMetadata().getEndTime().toString());
                for (ApiTimeSeriesData apiTimeSeriesData : apiTimeSeries.getData()) {
                    MetricData data = new MetricData();
                    // 在Data中插入EntityName,避免重复数据的产生
                    data.seHostname(apiTimeSeries.getMetadata().getEntityName());
                    // CM默认得到的时间格式为 EEE MMM dd HH:mm:ss 'CST' yyyy,转换时间格式为 yyyy-MM-dd HH:mm:ss
                    data.setTimestamp(dateUtils.parse(apiTimeSeriesData.getTimestamp().toString()));
                    data.setType(apiTimeSeriesData.getType());
                    data.setValue(apiTimeSeriesData.getValue());
                    dataList.add(data);
                }
                metric.setData(dataList);
                metrics.add(metric);
            }
        }
        return metrics;
    }
}

注意:

  • 代码中涉及到的DateUtils需要自己去进行实现
  • 通过这部分代码可以通过传入tsquery的方式去获取对应的idc集群的metric信息;接下来的代码我们只需要通过ServiceImpl去实现对应的监控指标的获取代码即可
  • 如果想通过cm api与spring boot整合的,这其中还会遇到2个问题:
    • 依赖冲突问题,主要表现在jackson与cxf的冲突;通过排jar包的方式可以解决
    • 正则解析错误,该问题为cm使用过程中的一个坑,目前仍在排查当中,具体表现形式为:
      在这里插入图片描述
      这里面有个空格,因此在编译的过程中直接会报正则解析的错误;但是我们可以发现在cm 6.x的api版本中已经没有这个问题了:
      在这里插入图片描述
      因此可以直接升级api的版本来解决该问题,但是随之带来的问题就是与线上运行的cm版本不一致(线上的版本为5.13.2),因此对于如何解决仍然需要思考;不过经过测试发现,使用cm 6.x版本的api,对于目前线上那套版本的相关指标并不影响
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值