JanusGraph: OLAP Traversals with Spark On Yarn-Client Mode

问题背景

JanusGraph 支持使用 Spark 进行一些 OLAP 计算。官方文档中只给出了 Spark Local 模式和 Spark Standalone Cluster 模式的例子。参考:JanusGraph with TinkerPop’s Hadoop-Gremlin

由于我们的大部分 Spark 是运行在 Yarn 上面的,尝试通过 Gremlin Console 使用 Spark On Yarn-Client 模型运行 JanusGraph 的 OLAP 任务。

JanusGraph 我们是用于 Atlas 的存储,也做一些 Atlas 的适配。

版本信息:

1
2
3
4
JanusGraph: 0.5.1
Spark: 2.4.0
Hadoop: 2.7.7
Atlas 2.1.0

环境适配

打包安装

1
2
3
4
mvn clean install -Pjanusgraph-release -Dgpg.skip=true -DskipTests=true

# 安装包
janusgraph-dist/target/janusgraph-0.5.1.zip

依赖整理

由于 Janusgraph-Hadoop 并没有引入 spark-yarn 和 相关 jar 包。所以想要支持 Spark On Yarn 模式运行必须要加入相关的依赖。
直接下载 Spark 2.4.0 的安装包,将 jars 里面的 jar 包放在 ${JANUSGRAPH_HOME}/ext/spark/jars 中。

1
2
3
4
5
6
wget https://archive.apache.org/dist/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz
tar xzvf spark-2.4.0-bin-hadoop2.7.tgz
cp ${SPARK_HOME}/jars/* ${JANUSGRAPH_HOME}/ext/spark/jars

# 去掉冲突 Jar 包
rm -f ${JANUSGRAPH_HOME}/ext/spark/jars/guava-14.0.1.jar

需要支持 Atlas,顾也加上 Atlas 相关 Jar 包。

1
2
3
4
5
6
cp ${ATLAS_HOME}/server/webapp/atlas/WEB-INF/lib/* ${JANUSGRAPH_HOME}/ext/atlas/jars

# 去掉冲突 Jar 包
rm -f ${JANUSGRAPH_HOME}/ext/atlas/jars/atlas-webapp-2.1.0.jar
rm -f ${JANUSGRAPH_HOME}/ext/atlas/jars/netty-3.10.5.Final.jar
rm -f ${JANUSGRAPH_HOME}/ext/atlas/jars/netty-all-4.0.52.Final.jar

启动脚本

编辑 gremlin.sh,做了如下配置:

  • 配置 SPARK_HOME
  • 配置 HADOOP_CONF_DIR 和 HBASE_CONF_DIR 并加入 CLASSPATH
  • 配置 HADOOP_GREMLIN_LIBS,通过 SparkContext addJar 方式引入依赖。
1
2
3
4
5
export SPARK_HOME=${JANUSGRAPH_HOME}/ext/spark
export HADOOP_GREMLIN_LIBS=${JANUSGRAPH_HOME}/ext/spark:${JANUSGRAPH_HOME}/ext/atlas:${JANUSGRAPH_HOME}/lib
export HADOOP_CONF_DIR=/etc/hadoop/conf
export HBASE_CONF_DIR=/etc/hbase/conf
export CLASSPATH=$CLASSPATH:$HADOOP_CONF_DIR:HBASE_CONF_DIR

JanusGraph 配置

hadoop-graph 配置

JanusGraph 后端使用 HBase 作为存储。

配置 ${JANUSGRAPH_HOME}/conf/hadoop-graph/read-hbase.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#
# Hadoop Graph Configuration
#
gremlin.graph=org.apache.tinkerpop.gremlin.hadoop.structure.HadoopGraph
gremlin.hadoop.graphReader=org.janusgraph.hadoop.formats.hbase.HBaseInputFormat
gremlin.hadoop.graphWriter=org.apache.hadoop.mapreduce.lib.output.NullOutputFormat

gremlin.hadoop.jarsInDistributedCache=true
gremlin.hadoop.inputLocation=none
gremlin.hadoop.outputLocation=output
gremlin.spark.persistContext=true

#
# JanusGraph HBase InputFormat configuration
#
janusgraphmr.ioformat.conf.storage.backend=hbase
janusgraphmr.ioformat.conf.storage.hostname=*****
janusgraphmr.ioformat.conf.storage.hbase.table=apache_atlas_janus

#
# SparkGraphComputer Configuration
#
#spark.master=local[*]
#spark.executor.memory=1g
spark.master=yarn-client
spark.executor.memory=2g
spark.executor.instances=4
spark.yarn.principal=******
spark.yarn.keytab=******.keytab
spark.serializer=org.apache.spark.serializer.KryoSerializer
spark.kryo.registrator=org.janusgraph.hadoop.serialize.JanusGraphKryoRegistrator

日志配置

修改 ${JANUSGRAPH_HOME}/conf/log4j-console.properties 配置

1
2
3
4
5
6
7
8
9
10
11
# 添加 Rolling_File Log Appender
log4j.appender.Rolling_File=org.apache.log4j.RollingFileAppender
log4j.appender.Rolling_File.Threshold=INFO
log4j.appender.Rolling_File.File=logs/gremlin.log
log4j.appender.Rolling_File.Append=true
log4j.appender.Rolling_File.MaxFileSize=100MB
log4j.appender.Rolling_File.MaxBackupIndex=10
log4j.appender.Rolling_File.layout=org.apache.log4j.PatternLayout
log4j.appender.Rolling_File.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss,SSS} [%C]-[%p] %m%n

log4j.rootLogger=${gremlin.log4j.level}, A2, Rolling_File

启动时可通过 -l 修改日志级别

1
bin/gremlin.sh -l info

执行 Hive Table Count 任务

启动 Gremlin Console:bin/gremlin.sh (可加上 -l info 指定日志级别)。

执行下面语句统计 hive_table 数量,可查看 logs/gremlin.log 日志信息,可以看到 Spark on yarn 的 application 信息。

1
2
3
graph = GraphFactory.open('conf/hadoop-graph/read-hbase.properties')
g = graph.traversal().withComputer(SparkGraphComputer)
g.V().has("__typeName", "hive_table").count()

报错 groovy 脚本

保存一个 groovy 初始化脚本,不用每次都初始化 graph。

编辑 ${JANUSGRAPH_HOME}/scripts/graph-spark.groovy

1
2
graph = GraphFactory.open('conf/hadoop-graph/read-hbase.properties')
g = graph.traversal().withComputer(SparkGraphComputer)

使用 graph-spark.groovy 初始化 脚本启动 gremlin console

1
bin/gremlin.sh -i scripts/graph-spark.groovy