0670-6.2.0-如何获取CDSW中每个Session输出的LiveLog日志

Fayson的github: https://github.com/fayson/cdhproject

推荐关注微信公众号:“Hadoop实操”,ID:gh_c4c535955d0f

1 文档编写目的

一些用户为了方便管理和审计,需要将CDSW上所有用户启动Session时运行代码输出的信息获取到。那接下来Fayson主要介绍如何通过获取用户每个Session代码运行输出的详细LiveLog日志。

内容概述
1.环境准备
2.获取livelog日志
3.总结

测试环境
1.Redhat7.4
2.CDH6.2.0
3.CDSW1.5.0

2 CDSW的LiveLog存储

经过对CDSW应用的分析,发现用户在CDSW启动Session后运行代码输出的日志最终是通过CDSW中提供的Docker容器livelog服务进行处理。Livelog日志最终保存方式是在CDSW的数据目录/var/lib/cdsw/current目录下的livelog数据目录中。

在这里插入图片描述
在livelog目录下查看目录中的OPTIONS-000033数据文件中,发现CDSW的livelog存储使用了FaceBook开放的一种嵌入式、持久化存储、KV型且适用于Fast Storage的存储引擎RocksDB。

在这里插入图片描述
在上面通过CDSW的livelog数据目录找到了底层数据存储使用的RocksDB存储引擎,在github上查看发现该存储支持Java API接口,参考地址:

https://github.com/facebook/rocksdb/wiki/RocksJava-API-TODO

在这里插入图片描述

3 环境准备

在上面分析了CDSW的livelog底层存储方式,那接下来使用Java API的方式访问RocksDB存储的数据文件。接下来Fayson展示的Java工程主要实现了如下功能:

  • 通过CDSW的API获取所有正在运行及已停止运行的Session ID

  • 通过Java API加载RocksDB存储的数据文件

  • 通过前面获取到Session ID在RocksDB数据文件中查找相应的livelog日志

1.将CDSW服务器上的/var/lib/cdsw/current/livelog目录压缩下载至本地目录

在这里插入图片描述

2.创建一个Java工程用于解析RocksDB存储的数据文件,添加pom依赖

<dependencies>
  <dependency>
    <groupId>org.rocksdb</groupId>
    <artifactId>rocksdbjni</artifactId>
    <version>4.9.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.4</version>
  </dependency>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.58</version>
  </dependency>
</dependencies>

3.HttpUtils.java工具类主要实现通过认证的方式访问CDSW API接口

/**
 * 使用账号密码认证的方式GET请求
 * @param url
 * @param username
 * @param password
 * @return
 * @throws Exception
 */
public static String getAccess(String url, String username, String password) throws Exception {
    String result = null;

    URI uri = new URI(url);


    HttpHost target = new HttpHost(uri.getHost(),  uri.getPort(), uri.getScheme());

    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope(target.getHostName(), target.getPort()),
            new UsernamePasswordCredentials(username, password));
    CloseableHttpClient httpclient = HttpClients.custom()
            .setDefaultCredentialsProvider(credsProvider).build();
    try {

        // Create AuthCache instance
        AuthCache authCache = new BasicAuthCache();
        // Generate BASIC scheme object and add it to the local
        // auth cache
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(target, basicAuth);

        // Add AuthCache to the execution context
        HttpClientContext localContext = HttpClientContext.create();
        localContext.setAuthCache(authCache);

        HttpGet httpget = new HttpGet(url);

        System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target);
        CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);
        try {
            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            result = EntityUtils.toString(response.getEntity());
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }

    return result;
}

4.ScanLiveLog.java主要用于加载RocksDB数据文件及通过Session ID查找livelog

package com.fayson;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fayson.utils.HttpUtils;
import org.rocksdb.Options;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.rocksdb.RocksIterator;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * package: com.fayson
 * describe: 获取CDSW每个Session的日志输出
 * creat_user: Fayson
 * email: htechinfo@163.com
 * creat_date: 2019/7/6
 * creat_time: 11:13 PM
 * 公众号:Hadoop实操
 */
public class ScanLiveLog {

    private static final String dbPath = "/Users/fayson/Documents/develop/rocksdb/livelog";

    static {
        RocksDB.loadLibrary();
    }

    public static RocksDB rocksDB;

    public static void main(String[] args) {
        String sessionUrl = "http://master.hadoop.com/api/v1/site/dashboards?limit=30&offset=0&order_by=created_at&order_sort=desc&start_max=2019-07-06T22:54:06%2B08:00&start_min=2019-06-29T22:54:06%2B08:00";

        // Load rocksdb
        loadRocksDB(dbPath);
        try {
            //根据时间范围获取所有的Session
            String result = HttpUtils.getAccess(sessionUrl, "admin", "admin");
            JSONArray jsonArray = JSONArray.parseArray(result);
            jsonArray.forEach(action -> {
                JSONObject jsonObject = (JSONObject)action;
                String containerID = jsonObject.getString("id");

                Map<Integer, String> map = getContent(containerID);
                System.out.println(containerID + "------------" + map.size());

            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 加载RocksDB数据目录
     * @param dbPath
     */
    public static void loadRocksDB(String dbPath) {
        Options options = new Options();
        options.setCreateIfMissing(true);

        // 文件不存在,则先创建文件
        if (!Files.isSymbolicLink(Paths.get(dbPath))){
            System.out.println("CDSW livelog data director not exists");
        }
        try {
            rocksDB = RocksDB.open(options, dbPath);
        } catch (RocksDBException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据ContainerID获取livelog中所有的output信息
     * @param containerID
     * @return
     */
    public static Map<Integer, String> getContent(String containerID) {
        Map<Integer, String> map = new HashMap<>();
        int i = 0;
        String index = "\0\0\0\0\0\0\0\0\2";
        while(true) {
            String keyStr = containerID + "_output" +  index.replace((char)2, (char)i);
            String value = getValue(keyStr);
            System.out.println("key:" + keyStr + "," + "Value:" + value);
            if(value != null) {
                map.put(i, value);
                i++;
            } else {
                break;
            }
        }

        return map;
    }

    /**
     * 根据指定的Rowkey获取单条输出的日志信息
     * @param keyStr
     * @return
     */
    public static String getValue(String keyStr) {
        String result = null;
        byte[] key = keyStr.getBytes();
        try {
            byte[] getValue = rocksDB.get(key);
            if(getValue != null && getValue.length > 0) {
                result = new String(getValue);
            }
        } catch (RocksDBException e) {
            e.printStackTrace();
        }
        return result;
    }


    //  RocksDB.DEFAULT_COLUMN_FAMILY
    public static void testDefaultColumnFamily() throws RocksDBException, IOException {
        Options options = new Options();
        options.setCreateIfMissing(true);

        /**
         *  打印全部[key - value]
         */
        RocksIterator iter = rocksDB.newIterator();
        for (iter.seekToFirst(); iter.isValid(); iter.next()) {
            System.out.println("iter key:" + new String(iter.key()) + ", iter value:" + new String(iter.value()));
        }
    }
}

5.运行Java代码进行测试,获取指定Session ID的livelog的输出信息

在这里插入图片描述

4 总结

1.在CDSW中每个Session会话输出的日志数据通过Docker中的livelog服务将日志写入RocksDB最终存储在CDSW服务器的/var/lib/cdsw/current/livelog目录下。

2.RocksDB提供Java API接口,可以通过编写Java代码解析RocksDB数据文件,通过每个Session的ID生成Rowkey获取到输出的日志信息。

3.每个启动的Session会输出多条日志信息,所以在获取这个Session的所有输出时,需要通过组成动态的Rowkey(如:”5ldrhqr7w50oa5x2_output\0\0\0\0\0\0\0\0\0”)

4.每个Session运行产生的所有livelog信息都会存储在RocksDB中,由于存储的livelog日志中有clear记录,所以在CDSW界面上会自动的屏蔽掉被clear的日志。

GitHub地址:

https://github.com/fayson/cdhproject/tree/master/rocksdbexample

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值