1. Dependency
<properties>
<janus.version>1.0.0</janus.version>
<tinkerpop.version>3.7.0</tinkerpop.version>
</properties>
<dependency>
<groupId>org.janusgraph</groupId>
<artifactId>janusgraph-driver</artifactId>
<version>${janus.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>tinkerpop</artifactId>
<version>${tinkerpop.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<!-- optional -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.yaml</include>
</includes>
</resource>
</resources>
</build>
2. Structure
📒 src/main/resources
📂 conf
📄 remote-objects.yaml
📂 META-INF/spring/
# content:io.os.tinkerpop.autoconfigure.GremlinClusterAutoConfiguration
📄 org.springframework.boot.autoconfigure.AutoConfiguration.imports
3. Starter
3.1. TinkerpopProperties
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "io.os.tinkerpop")
public class TinkerpopProperties{
private String traversalName = "g";
private String configFile = "src/main/resources/conf/remote-objects.yaml";
public String getTraversalName() {
return traversalName;
}
public void setTraversalName(String traversalName) {
this.traversalName = traversalName;
}
public String getConfigFile() {
return configFile;
}
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
}
3.2. TinkerpopRepository
import org.apache.tinkerpop.gremlin.driver.Client;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.springframework.stereotype.Repository;
@Repository
public class TinkerpopRepository {
protected Client client;
protected GraphTraversalSource g;
public TinkerpopRepository(GraphTraversalSource g,Client client) {
this.g = g;
this.client = client;
}
}
3.3. GremlinClusterAutoConfiguration
-
src/main/resources/META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.elf.dp.tinkerpop.config.GremlinClusterAutoConfiguration
import org.apache.tinkerpop.gremlin.driver.Client;
import org.apache.tinkerpop.gremlin.driver.Cluster;
import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GremlinClusterAutoConfiguration {
@Autowired
private TinkerpopProperties tp;
@Bean
@ConditionalOnMissingBean
Cluster cluster() throws Exception {
return Cluster.open(tp.getConfigFile());
}
@Bean
@ConditionalOnMissingBean
Client client() throws Exception {
return cluster().connect();
}
@Bean
@ConditionalOnMissingBean
RemoteConnection remoteConnection(final Cluster cluster) {
String traversalName = tp.getTraversalName();
return DriverRemoteConnection.using(cluster,traversalName);
}
@Bean
@ConditionalOnMissingBean
GraphTraversalSource graphTraversalSource(
final RemoteConnection remoteConnection) throws Exception {
return AnonymousTraversalSource.traversal()
.withRemote(remoteConnection);
}
}
3.4. 注意事项
-
连接使用GraphBinary和janusgraph-driver,
它不允许访问内部JanusGraph组件,如ManagementSystem,
要访问ManagementSystem,必须更新包和序列化. -
janusgraph-driver包替换为janusgraph-core包
-
conf/remote-objects.yaml替换className序列化类,
GraphBinaryMessageSerializerV1替换为GryoMessageSerializerV1d0,
最新版Gremlin序列化类是GryoMessageSerializerV3d0,
org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1
org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0
4. Application
4.1. 引入starter
<dependency>
<groupId>io.os.starter</groupId>
<artifactId>starter-tinkerpop</artifactId>
</dependency>
4.2. remote-objects.yaml
hosts: [192.168.9.111]
port: 8182
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0,
config: {
ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry]
}
}
# 推荐4K
connectionPool: {maxContentLength: 6553600}
4.3. application.yaml
server:
port: 8080
servlet:
context-path: /tinkerpop
logging:
level:
root: warn
'[org.apache.tinkerpop.gremlin.driver]': warn
'[io.os.gremlin]': debug
io:
os:
tinkerpop:
traversalName: g
configFile: src/main/resources/conf/remote-objects.yaml
4.4. Repository
import java.util.List;
import java.util.Map;
import org.apache.tinkerpop.gremlin.driver.Client;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.springframework.stereotype.Repository;
@Repository
public class LineageRepository extends TinkerpopRepository{
public LineageRepository(GraphTraversalSource g,Client client) {
super(g, client);
}
public List<Map<Object,Object>> getLineageByGuid() {
return g.V().elementMap().toList();
}
}
4.5. Connector
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import org.apache.tinkerpop.gremlin.driver.Cluster;
import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1;
import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
public class TinkerpopConnector {
private static final Logger logger = LoggerFactory
.getLogger(MethodHandles.lookup().lookupClass());
//connect("192.168.9.111",8182);
public static void connect(final String host,final int port) {
if (StringUtils.hasText(host)) {
String msg = String.format("%s can not be blank!",host);
throw new IllegalArgumentException(msg);
}
if (port < 1) {
throw new IllegalArgumentException("invalid port!");
}
Cluster.Builder builder = Cluster.build();
builder.addContactPoint(host);
builder.port(port);
builder.serializer(new GraphBinaryMessageSerializerV1());
Cluster cluster = builder.create();
GraphTraversalSource g = AnonymousTraversalSource.traversal()
.withRemote(DriverRemoteConnection.using(cluster));
Long count = g.V().count().next();
List<Map<Object, Object>> resultMapList = g.V().elementMap().toList();
logger.info("janus record count:{}",count);
resultMapList.forEach(resultMap -> {
logger.info(resultMap.toString());
});
cluster.close();
}
}
5. Python Collector
一些gremlin步骤(step)和谓词(predicate)名称在python中是关键字,
在Gremlin-Python中只能以_为后缀,如in()变为in_(),not()变为not_()等,
受影响的其它名称如all,and,as,from,global,is,list,or和set.
5.2. 导入相关包
from gremlin_python import statics
from gremlin_python.structure.graph import Graph
from gremlin_python.process.graph_traversal import __
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection