温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。
Fayson的github: https://github.com/fayson/cdhproject
提示:代码块部分可以左右滑动查看噢
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工程主要实现了如下功能:
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
提示:代码块部分可以左右滑动查看噢
为天地立心,为生民立命,为往圣继绝学,为万世开太平。 温馨提示:如果使用电脑查看图片不清晰,可以使用手机打开文章单击文中的图片放大查看高清原图。