(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 hostname
storage.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=elasticsearch
index.search.hostname=192.168.1.22
1.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是一个单例,所以直接初始化一下就行了。
相关文章