随着社交、电商、金融、零售、物联网等行业的快速发展,现实社会织起了了一张庞大而复杂的关系网,亟需一种支持海量复杂数据关系运算的数据库即图数据库。本系列文章是学习知识图谱以及图数据库相关的知识梳理与总结
本文会包含如下内容:
- hugegraph的首次启动过程:初始化图的后端数据库
- hugegraph的非首次启动过程:正常启动图数据库
本篇文章适合人群:架构师、技术专家、对知识图谱与图数据库感兴趣的高级工程师
1. 搭建调试环境
从git上clone hugegraph的源码,导入IDEA中,并配置好gremlin-server.yaml、hugegraph.properties、rest-server.properties三个配置文件
代码地址:https://github.com/hugegraph/hugegraph, 如果从这个地方clone下载很慢,可以尝试这个【hub.fastgit.org是git的一个镜像加速网站】:https://hub.fastgit.org/hugegraph/hugegraph
本次分析基于hugegraph 0.11.2进行。
1.1 如何在IDE中启动
hugegraph的启动分为"首次启动"和"非首次启动",这么区分是因为在第一次启动前需要初始化后端数据库,然后启动服务。 而在人为停掉服务后,或者其他原因需要再次启动服务时,因为后端数据库是持久化存在的,直接启动服务即可。
首次启动的入口类是: com.baidu.hugegraph.cmd.InitStore,需要提供两个参数:gremlin-server.yaml,rest-server.properties,在配置run的程序参数中,需要是绝对路径。
非首次启动的入口类是:com.baidu.hugegraph.dist.HugeGraphServer,需要提供两个参数:gremlin-server.yaml,rest-server.properties,在配置run的程序参数中,需要是绝对路径。
注意:除参数中指定的配置文件外,需要正确配置图对应的配置文件,文件名格式是:图名称.properties, 如hugegraph.properties。
在gremlin-server, rest-server中能在graphs配置项中配置多个图,graphs配置项是一个 map 结构,key 是图的名字,value 是该图的配置文件路径
2. 首次启动过程
在第一次启动前需要初始化后端数据库,过程如下(详细过程参见代码):
-
检查参数是否正确,必须提供gremlin-server.yaml,rest-server.properties两个配置文件的路径
-
注册后端存储,目前支持的后端存储是:cassandra, scylladb, rocksdb, mysql, palo, hbase, postgresql,在backend.properties文件中配置
-
注册插件, 通过ServiceLoader.load(HugeGraphPlugin.class) 加载插件
-
加载gremlinConfFile,并检查graphs配置项是否配置正确
-
针对配置的每个图,进行初始化,不同的后端存储,初始化逻辑不同,针对MySQL,主要是创建图对应的数据库及数据表
-
针对RestServer,初始化admin用户StandardAuthenticator.initAdminUser(restConfFile);
-
关闭并释放资源 HugeFactory.shutdown(30L);
public static void main(String[] args) throws Exception {
E.checkArgument(args.length == 2,
"HugeGraph init-store can only accept two config files");
E.checkArgument(args[0].endsWith(".yaml"),
"Expect the 1st parameter is yaml config file");
E.checkArgument(args[1].endsWith(".properties"),
"Expect the 2nd parameter is properties config file");
String gremlinConfFile = args[0];
String restConfFile = args[1];
RegisterUtil.registerBackends();
RegisterUtil.registerPlugins();
RegisterUtil.registerServer();
YamlConfiguration config = new YamlConfiguration();
config.load(gremlinConfFile);
List<ConfigurationNode> nodes = config.getRootNode()
.getChildren(GRAPHS);
E.checkArgument(nodes.size() == 1,
"Must contain one '%s' node in config file '%s'",
GRAPHS, gremlinConfFile);
List<ConfigurationNode> graphNames = nodes.get(0).getChildren();
E.checkArgument(!graphNames.isEmpty(),
"Must contain at least one graph");
for (ConfigurationNode graphName : graphNames) {
@SuppressWarnings("unchecked")
String name = ((Map.Entry<String, Object>)
graphName.getReference()).getKey();
HugeFactory.checkGraphName(name, "gremlin-server.yaml");
String configPath = graphName.getValue().toString();
initGraph(configPath);
}
StandardAuthenticator.initAdminUser(restConfFile);
HugeFactory.shutdown(30L);
}
3. 非首次启动过程
HugeGraphServer中启动2个Server, 使用gremlin-server.yaml配置文件启动HugeGremlinServer,使用rest-server.properties配置文件启动HugeRestServer
3.1 HugeGremlinServer
HugeGremlinServer 本身是启动一个ContextGremlinServer,通过实现GremlinPlugin的接口以达到针对Gremlin的支持,相关的配置如下:
scriptEngines: {
gremlin-groovy: {
plugins: {
com.baidu.hugegraph.plugin.HugeGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {
classImports: [
java.lang.Math,
com.baidu.hugegraph.backend.id.IdGenerator,
com.baidu.hugegraph.type.define.Directions,
com.baidu.hugegraph.type.define.NodeRole,
com.baidu.hugegraph.traversal.algorithm.CustomizePathsTraverser,
com.baidu.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser,
com.baidu.hugegraph.traversal.algorithm.FusiformSimilarityTraverser,
com.baidu.hugegraph.traversal.algorithm.HugeTraverser,
com.baidu.hugegraph.traversal.algorithm.NeighborRankTraverser,
com.baidu.hugegraph.traversal.algorithm.PathsTraverser,
com.baidu.hugegraph.traversal.algorithm.PersonalRankTraverser,
com.baidu.hugegraph.traversal.algorithm.ShortestPathTraverser,
com.baidu.hugegraph.traversal.algorithm.SubGraphTraverser,
com.baidu.hugegraph.traversal.optimize.Text,
com.baidu.hugegraph.traversal.optimize.TraversalUtil,
com.baidu.hugegraph.util.DateUtil
],
methodImports: [java.lang.Math#*]
},
org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {
files: [scripts/empty-sample.groovy]
}
}
}
}
3.2 HugeRestServer
-
HugeRestServer 本身是启动一个glassfish应用服务器的HttpServer, 通过在构建RestServer实例时,加载配置文件new RestServer(new HugeConfig(conf));
-
通过构建ApplicationConfig注册componentClass,注册的componentClass详见如下代码,通过GraphManagerFactory加载配置的所有graph, WorkLoad简单的实现httpServer负载的控制,RolesAllowedDynamicFeature实现简单的权限控制(因为一些操作如顶点、边、图等操作只能admin用户操作,这类操作被@RolesAllowed 注解)
-
在com.baidu.hugegraph.api package下提供针对图的种类操作的Rest API
public ApplicationConfig(HugeConfig conf) { packages("com.baidu.hugegraph.api"); // Register Jackson to support json register(org.glassfish.jersey.jackson.JacksonFeature.class); // Register to use the jsr250 annotations @RolesAllowed register(RolesAllowedDynamicFeature.class); // Register HugeConfig to context register(new ConfFactory(conf)); // Register GraphManager to context register(new GraphManagerFactory(conf)); // Register WorkLoad to context register(new WorkLoadFactory()); // Let @Metric annotations work MetricRegistry registry = MetricManager.INSTANCE.getRegistry(); register(new InstrumentedResourceMethodApplicationListener(registry)); }