(4)JanusGraph学习-----connect via JAVA
1.通过内嵌方式访问JG
通过前文了解到JG本身就是一堆jar包,没有执行线程。所以两种访问方式,一种是通过现在服务器上启动一个gremlin-server (第三节中的内容) 。一种就是jar包内嵌的客户系统中,也就是要放到一个main函数或者spring web容器中去执行jg的jar包。
这里主要通过调用JG的相关java依赖包,结合配置文件,通过JanusGraphFactory.open()来访问对应的图库。首先演示通过main或者单元测试来跑通JG连接。
为了大家更好的理解内嵌的方式,大家可以:首先kill第三节中gremlin-server服务进程,再删除数据。(hbase和ES索引)
首先参考官方给出的example,构建出如下的目录结构:
相关核心代码:
1.1GraphDB类
主要封装一些统一的方法。这里我们通过GraphFactory.open(conf)方法来打开图库。注意通过查看源码可以得知:配置文件中必须定义key:gremlin.graph。GraphFactory会调用对应的指定工厂类的open代码。考虑后期扩展性,所以这里不直接写死JanusGraphFactory.open()。
public class GraphDB { private static final Logger LOGGER = LoggerFactory.getLogger(GraphDB.class); protected String propFileName; protected Configuration conf; protected Graph graph; protected GraphTraversalSource g; protected boolean supportsTransactions; protected boolean supportsSchema; protected boolean supportsGeoshape; public GraphDB(final String fileName) { this.propFileName = fileName; } public GraphTraversalSource openGraph() throws ConfigurationException { LOGGER.info("[andlinks]: opening graph"); conf = new PropertiesConfiguration(propFileName); graph = GraphFactory.open(conf); g = graph.traversal(); return g; } public GraphTraversalSource createGraph() { return null; } public void closeGraph() throws Exception { LOGGER.info("[andlinks]:closing graph"); try { if (g != null) { g.close(); } if (graph != null) { graph.close(); } } finally { g = null; graph = null; } } ** * Drops the graph instance. The default implementation does nothing. */ public void dropGraph() throws Exception { } ** * Creates the graph schema. The default implementation does nothing. */ public void createSchema() { }}1.2 JanusGraphDB类
继承GraphDB类,提供一系列图操作接口。
public class JanusGraphDB extends GraphDB{ private static final Logger LOGGER= LoggerFactory.getLogger(JanusGraph.class); public JanusGraphDB(final String fileName) { super(fileName); this.supportsSchema = true; this.supportsTransactions = true; this.supportsGeoshape = true; } @Override public GraphTraversalSource openGraph() throws ConfigurationException { super.openGraph(); return g; } @Override public GraphTraversalSource createGraph() { return super.createGraph(); } @Override public void dropGraph() throws Exception { if (graph != null) { JanusGraphFactory.drop(getJanusGraph()); } } protected JanusGraph getJanusGraph() { return (JanusGraph) graph; } @Override public void createSchema() { final JanusGraphManagement management = this.getJanusGraph().openManagement(); try { naive check if the schema was previously created// if (management.getRelation*(RelationType.class).iterator().hasNext()) {// management.rollback();// return;// } LOGGER.info("[andlinks]:creating schema");// createProperties(management); createVertexLabels(management);// createEdgeLabels(management);// createCompositeIndexes(management);// createMixedIndexes(management); management.commit(); } catch (Exception e) { management.rollback(); } } ** * Creates the vertex labels. */ protected void createVertexLabels(final JanusGraphManagement management) { management.makeVertexLabel("titan").make(); management.makeVertexLabel("location").make(); management.makeVertexLabel("god").make(); management.makeVertexLabel("demigod").make(); management.makeVertexLabel("human").make(); management.makeVertexLabel("monster").make(); }}1.3 janusgraph-hbase-es.properties配置文件
这里没有配置graph.graphname的话,默认是janusgraph图库。对应的hbase表名和图库名一致。后期如果要做多图配置的话,需要设置该key。
gremlin.graph=org.janusgraph.core.JanusGraphFactory#graph.graphname=cc#graph.graphname=ConfigurationManagementGraph# 存储后端配置storage.backend=hbase# your zookper hostnamestorage.hostname=192.168.1.22# mac os中:如果你想远程连接 还需要做的是 把hbase的host文件copy过来放到你的本机的hosts文件中# 缓存配置# cache.db-cache = true# cache.db-cache-clean-wait = 20åå# cache.db-cache-time = 180000# cache.db-cache-size = 0.5# es 配置index.search.backend=elasticsearchindex.search.hostname=192.168.1.221.4 pom文件
一开始直接使用了janusgraph-all依赖包,内部包含了所有的JG依赖。类似于springboot。但是实际启动过程中会报各种class not found错误。查看依赖树发现是多个版本冲突导致。考虑多个jar冲突报错和后期第三方jar包的增加,这里单独引用需要用到的小依赖。需要注意下hbase-shaded-client和elasticsearch-rest-client的版本,试过几次才找到对应的可用版本。具体的报错信息见末尾的报错总结。
<dependencies> <!--<dependency>--> <!--<groupId>org.janusgraph</groupId>--> <!--<artifactId>janusgraph-all</artifactId>--> <!--<version>${jg.version}</version>--> <!--</dependency>--> <dependency> <groupId>org.janusgraph</groupId> <artifactId>janusgraph-core</artifactId> <version>${jg.version}</version> </dependency> <!--<dependency>--> <!--<groupId>com.fasterxml.jackson.core</groupId>--> <!--<artifactId>jackson-core</artifactId>--> <!--<version>2.6.2</version>--> <!--</dependency>--> <!--<dependency>--> <!--<groupId>org.apache.httpcomponents</groupId>--> <!--<artifactId>httpcore</artifactId>--> <!--<version>4.2.3</version>--> <!--</dependency>--> <dependency> <groupId>org.apache.tinkerpop</groupId> <artifactId>gremlin-server</artifactId> <version>${tinkerpop.version}</version> </dependency> <dependency> <groupId>org.janusgraph</groupId> <artifactId>janusgraph-hbase</artifactId> <version>${jg.version}</version> <!--<scope>runtime</scope>--> </dependency> <dependency> <groupId>org.janusgraph</groupId> <artifactId>janusgraph-es</artifactId> <version>${jg.version}</version> </dependency> <!--<dependency>--> <!--<groupId>org.apache.hbase</groupId>--> <!--<artifactId>hbase-common</artifactId>--> <!--<version>1.2.0-cdh5.12.1</version>--> <!--</dependency>--> <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-shaded-client</artifactId> <version>1.2.6</version> <!--<scope>runtime</scope>--> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>6.2.2</version> </dependency> </dependencies> <repositories> <repository> <id>maven-hadoop</id> <name>Hadoop Releases</name> <url>https://repository.cloudera.com/content/repositories/releases/</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>1.5 JanusGraphDBTest类
这里直接先使用单元测试,初步判断下是否能够成功。
public class JanusGraphDBTest{
protected static final String CONF_FILE = "src/main/resources/conf/janusgraph-hbase-es.properties"; private static JanusGraphDB janusGraphDB; private static GraphTraversalSource g; private static JanusGraphManager gm; static { janusGraphDB = new JanusGraphDB(CONF_FILE); if(JanusGraphManagerUtility.getInstance()==null){ gm = new JanusGraphManager(new Settings()); } try { g = janusGraphDB.openGraph(); } catch (ConfigurationException e) { e.printStackTrace(); } } @Test public void createSchema(){ janusGraphDB.createSchema(); final JanusGraph janusGraph = (JanusGraph) g.getGraph(); final JanusGraphManagement management = janusGraph.openManagement(); final List<String> vertexLabels = StreamSupport.stream(management.getVertexLabels().spliterator(), false) .map(Namifiable::name).collect(Collectors.toList()); final List<String> expectedVertexLabels = Stream.of("titan", "location", "god", "demigod", "human", "monster") .collect(Collectors.toList()); assertTrue(vertexLabels.containsAll(expectedVertexLabels)); } @Test public void selectCount(){ Long count = g.V().count().next(); System.out.println("CC+++++++:"+count.toString()); } @Test public void dropGraph() throws Exception { janusGraphDB.dropGraph(); }}单元测试成功的话,会在hbase中查看到对应创建的table。es索引创建可能不成功。这个我们后面章节再介绍进一步配置,先保证连接,建图成功。
2.踩坑过程中碰到的问题记录:
2.1 Caused by: java.lang.NoSuchMethodError:org.apache.hadoop.hbase.HTableDescriptor.addFamily(Lorg/apache/hadoop/hbase/HColumnDescriptor;)Lorg/apache/hadoop/hbase/HTableDescriptor;
at org.janusgraph.diskstorage.hbase.HBaseCompat1_0.addColumnFamilyToTableDescriptor(HBaseCompat1_0.java:49)
at org.janusgraph.diskstorage.hbase.HBaseStoreManager.createTable(HBaseStoreManager.java:761)
at org.janusgraph.diskstorage.hbase.HBaseStoreManager.ensureTableExists(HBaseStoreManager.java:744)
at org.janusgraph.diskstorage.hbase.HBaseStoreManager.getLocalKeyPartition(HBaseStoreManager.java:536)
at org.janusgraph.diskstorage.hbase.HBaseStoreManager.getDeployment(HBaseStoreManager.java:375)
【解决方案】:hbase-shaded-client依赖包版本不对,这里使用hbase对应的版本版反而会报错,查看源码,需要和janusgraph-core对应的依赖包版本一致才行。可以在janusgraph-all中查看对应的版本号,然后单独引入对应的依赖即可。
2.2
Caused by: java.lang.IllegalArgumentException: Could not instantiate implementation: org.janusgraph.diskstorage.es.ElasticSearchIndex
at org.janusgraph.util.system.ConfigurationUtil.instantiate(ConfigurationUtil.java:64)
at org.janusgraph.diskstorage.Backend.getImplementationClass(Backend.java:476)
at org.janusgraph.diskstorage.Backend.getIndexes(Backend.java:463)
at org.janusgraph.diskstorage.Backend.<init>(Backend.java:148)
at org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.getBackend(GraphDatabaseConfiguration.java:1840)
at org.janusgraph.graphdb.database.StandardJanusGraph.<init>(StandardJanusGraph.java:138)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:160)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:131)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:111)
... 30 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.janusgraph.util.system.ConfigurationUtil.instantiate(ConfigurationUtil.java:58)
... 38 more
Caused by: org.janusgraph.diskstorage.PermanentBackendException: listener timeout after waiting for [30000] ms
【解决方案】:这里通过进一步查看debug日志,发现次连接es是成功的,说明es服务本身没有问题,所以初步定位问题出现在jar包上,通过尝试,更新elasticsearch-rest-client 的6.2.2版本jar包后解决。(查看日志发现应该是路由ip解析的问题,6.2.2版本jar包能够解析到本机的内网ip,而6.0.1版本解析不到。这里暂时不花时间深究。)
2.3
Caused by: java.lang.IllegalStateException: Gremlin Server must be configured to use the JanusGraphManager.
at com.google.common.base.Preconditions.checkState(Preconditions.java:173)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:148)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:131)
at org.janusgraph.core.JanusGraphFactory.open(JanusGraphFactory.java:111)
【解决方案】:这里需要初始化JanusGraphManager才能够创建graph实例。这个是在配置文件中配置了key:graph.graphname之后才会报错,需要在代码中手动初始化一下,因为JanusGraphManager是一个单例,所以直接初始化一下就行了。
相关文章