JanusGraph基于Spark on yarn 的OLAP

使用JanusGraph的OLAP记录

本文主要描述在windows的idea中使用 JanusGraph的spark on yarn任务分析,主要用于学习和交流。

环境配置:

  1. 19个RegionServer组成的HBase集群。
  2. 每个节点由7块磁盘组成
  3. 每个节点2个物理CPU,逻辑CPU核数40核

对于普通的查询 例如:g.V().count() 对于图库中点数量少的情况可以使用,对于量大的请款已经无法满足,不是慢而是根本就查不出来。

如下在一个存了半年的通联关系的图库中使用查询命令,直接报错。

首先在在命令行使用properties文件开启graph:

[hadoop@master bin]$ ./gremlin.sh
gremlin> graph=JanusGraphFactory.open('conf/njm-graph.properties')
==>standardjanusgraph[hbase:[IP地址]]
gremlin> g=graph.traversal()

njm-graph.properties 配置文件中个使用HBase作为后端存储,使用ES作为索引。

紧接着使用如下语句,查询点个数,等了非常长的时间,直接报错,试了好几次都是如下情况:

gremlin> g.V().count()
11:04:19 WARN  org.janusgraph.graphdb.transaction.StandardJanusGraphTx  - Query requires iterating over all vertices [()]. For better performance, use indexes
java.io.IOException: Failed to get result within timeout, timeout=60000ms
Type ':help' or ':h' for help.
Display stack trace? [yN]12:45:19 WARN  org.apache.hadoop.hbase.client.ConnectionManager$HConnectionImplementation  - This client just lost it's session with ZooKeeper, closing it. It will be recreated next time someone needs it
org.apache.hadoop.hbase.shaded.org.apache.zookeeper.KeeperException$SessionExpiredException: KeeperErrorCode = Session expired
    at org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher.connectionEvent(ZooKeeperWatcher.java:702)
    at org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher.process(ZooKeeperWatcher.java:613)
    at org.apache.hadoop.hbase.shaded.org.apache.zookeeper.ClientCnxn$EventThread.processEvent(ClientCnxn.java:522)
    at org.apache.hadoop.hbase.shaded.org.apache.zookeeper.ClientCnxn$EventThread.run(ClientCnxn.java:498)

使用OLAP的方式(什么是OLAP/OLTP这里不解释)

如下的方式为,在window的 idea中提交任务,使用spark on yarn的方式进行查询。命令行的方式也已经测试通了,这里就不记录了,毕竟生产中不会使用命令行。
而且这里直接使用 spark on yarn 的方式,官网中介绍了spark独立集群的方式,这里就不记录了,毕竟生产中spark on yarn用的多一些。

需要的配置文件及配置:

1. hadoop集群默认的配置文件3个:
    core-site.xml
    hdfs-site.xml
    yarn-site.xml

将如上3个文件拷贝到项目的resources目录下,在最开始测试的时候会出现一个报错,需要将core-size.xml中的最后一个注释掉,否则会报找不到文件:


2. pom.xml

在引用依赖时一定要注意,你引用的依赖中包含guava的依赖,一定要主要看你本地依赖和服务器集群上的guava的版本,##最好保持一致##。
前期也是解决guava依赖冲突,花了很长时间。


        
            org.apache.hadoop
            hadoop-yarn-server-web-proxy
            2.5.0
            
                
                    servlet-api
                    javax.servlet
                
                
                    guava
                    com.google.guava
                
            
        
        
            org.janusgraph
            janusgraph-core
            0.3.0
            
                
                    guava
                    com.google.guava
                
            
        
        
            org.janusgraph
            janusgraph-hadoop
            0.3.0
            
                
                    logback-classic
                    ch.qos.logback
                
            
        
        
            org.apache.tinkerpop
            gremlin-core
            3.3.3
        
        
            org.apache.tinkerpop
            spark-gremlin
            3.3.3
            
                
                    guava
                    com.google.guava
                
            
        
        
            org.apache.tinkerpop
            hadoop-gremlin
            3.3.3
        
        
            org.apache.spark
            spark-yarn_2.11
            2.2.0
            
                
                    guava
                    com.google.guava
                
            
        
        
            org.apache.hbase
            hbase-shaded-client
            1.2.6
        
        
            org.apache.hbase
            hbase-shaded-server
            1.2.6
        
        
        
            com.jcabi
            jcabi-log
            0.14
        
        
            javax.servlet
            servlet-api
            2.5
        
        
            org.janusgraph
            janusgraph-hbase
            0.3.0
        
    
3. read-hbase-hadoop.properties

这个配置文件是从JanusGraph的安装包目录/datas/disk22/janusgraph-0.3.0-hadoop2/conf/hadoop-graph中拷贝出来的,主要是配置后端存储
及序列化等配置,这里使用的是HBase+ES的配置,这个目录下有cassandra的配置,可以根据需要获取。

配置如下,其中spark.yarn.jars 配置非常重要:

#
# 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.tinkerpop.gremlin.hadoop.structure.io.gryo.GryoOutputFormat

gremlin.hadoop.jarsInDistributedCache=true
gremlin.hadoop.inputLocation=none
gremlin.hadoop.outputLocation=output
gremlin.spark.persistContext=true
gremlin.hadoop.defaultGraphComputer=org.apache.tinkerpop.gremlin.spark.process.computer.SparkGraphComputer

janusgraphmr.ioformat.conf.storage.backend=hbase
janusgraphmr.ioformat.conf.storage.hostname=IP地址
janusgraphmr.ioformat.conf.storage.hbase.ext.zookeeper.znode.parent=/hbase-unsecure
janusgraphmr.ioformat.conf.storage.hbase.table=graph_table

# 这个配置非常重要,原始配置文件中没有,这个指定的目录为spark的jar包,可以从集群spark目录中直接获取
# 我这里的目录为: /usr/hdp/current/spark2-client/jars/  224个jar包直接上传就对了
spark.yarn.jars=hdfs://IP地址:8020/user/hadoop/janusgraph/spark_jars/*.jar

#这里指定提交任务到yarn
spark.master=yarn
#spark的client模式,也就是提交任务后我本地作为JobManager,任务计算完成后会返回结果给我本地
spark.submit.deployMode=client
spark.executor.memory=20g
spark.executor.cores=6
spark.executor.instances=20
spark.driver.memory=1g

#序列化
spark.serializer=org.apache.spark.serializer.KryoSerializer
spark.kryo.registrator=org.apache.tinkerpop.gremlin.spark.structure.io.gryo.GryoRegistrator
4. 代码

在代码中需要指定一个 HADOOP_GREMLIN_LIBS配置,官网中还介绍了一种方式,在spark集群的每个节点上指定一个相同的目录
然后将需要依赖的jar包放上去,很明显没有指定一个hdfs路径方便。

public class GraphComputeApp {

    private static final Logger LOGGER = LoggerFactory.getLogger(GraphComputeApp.class);
    private final static String PROPERTY_FILE_PATH = "hadoop-graph/src/main/resources/read-hbase-hadoop.properties";

    public static void main(String[] args) throws Exception {

        //System.setProperty("user.name", "hadoop");
        System.setProperty("HADOOP_USER_NAME", "hadoop");
        
        //这个配置非常重要,这个指定一个HDFS路径,路径中存放jar包为JanusGraph安装目录解压后的依赖目录 janusgraph-0.3.0-hadoop2/lib
        //将目录中的jar包上传到hdfs上,任务运行时需要的依赖
        System.setProperty("HADOOP_GREMLIN_LIBS", "hdfs://ip:8020/user/hadoop/janusgraph/spark-yarn/jars/");

        Graph graph = GraphFactory.open(PROPERTY_FILE_PATH);
        GraphTraversalSource g = graph.traversal().withComputer(SparkGraphComputer.class);

        long count = g.V().count().next();
        LOGGER.info(count + "-----g.V().count()-------------------------------");
        long count_E = g.E().count().next();
        LOGGER.info(count_E + "-----g.E().count()-------------------------------");

        graph.close();
    }

}
5. 运行

做好各项配置后,直接在idea上运行main方法,在yarn上可以看到:


在yarn上已经发起的任务

spark上任务进度:


spark任务进度.png

在idea中可以看到如下日志:

[task-result-getter-0]2019-12-19 14:45:02 [INFO ] task-result-getter-0 | Finished task 2.0 in stage 0.0 (TID 52) in 48487 ms on slave23 (executor 19) (1/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[dispatcher-event-loop-1]2019-12-19 14:45:15 [INFO ] dispatcher-event-loop-1 | Added broadcast_0_piece0 in memory on slave12:14785 (size: 34.8 KB, free: 10.5 GB) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[dispatcher-event-loop-3]2019-12-19 14:45:17 [INFO ] dispatcher-event-loop-3 | Added broadcast_0_piece0 in memory on slave13:55393 (size: 34.8 KB, free: 10.5 GB) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[task-result-getter-1]2019-12-19 14:46:17 [INFO ] task-result-getter-1 | Finished task 1.0 in stage 0.0 (TID 51) in 122944 ms on slave20 (executor 7) (2/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[task-result-getter-2]2019-12-19 14:58:31 [INFO ] task-result-getter-2 | Finished task 3.0 in stage 0.0 (TID 53) in 857171 ms on slave5 (executor 3) (3/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[task-result-getter-3]2019-12-19 15:03:14 [INFO ] task-result-getter-3 | Finished task 5.0 in stage 0.0 (TID 55) in 1140160 ms on newslave200 (executor 18) (4/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[task-result-getter-0]2019-12-19 15:09:29 [INFO ] task-result-getter-0 | Finished task 72.0 in stage 0.0 (TID 19) in 1518252 ms on slave20 (executor 7) (5/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
[task-result-getter-1]2019-12-19 15:11:18 [INFO ] task-result-getter-1 | Finished task 0.0 in stage 0.0 (TID 50) in 1623848 ms on slave14 (executor 10) (6/98) | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)
省略很多行......

因为我在hbase上的这张表非常大,有98个分区。
执行过程非常慢,最终输出结果:

查询点个数.png
查询边个数.png

库中点的个数:351677990
库中边的个数:2139729335
耗时 5个多小时,因为是测试环境,还有很多数据在入库,还有其他表的操作查询及入库,所有还有很大的优化空间。

可以看到yarn上任务完成:


任务成功.png

有了初始化一个这样的graph后,可以做各种各样的图分析,也可以直接使用Gremlin提供的各种开箱即用图算法进行分析。

你可能感兴趣的:(JanusGraph基于Spark on yarn 的OLAP)