源码解析--hugegraph图数据库启动过程

随着社交、电商、金融、零售、物联网等行业的快速发展,现实社会织起了了一张庞大而复杂的关系网,亟需一种支持海量复杂数据关系运算的数据库即图数据库。本系列文章是学习知识图谱以及图数据库相关的知识梳理与总结

本文会包含如下内容:

  • 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. 首次启动过程

在第一次启动前需要初始化后端数据库,过程如下(详细过程参见代码):

  1. 检查参数是否正确,必须提供gremlin-server.yaml,rest-server.properties两个配置文件的路径

  2. 注册后端存储,目前支持的后端存储是:cassandra, scylladb, rocksdb, mysql, palo, hbase, postgresql,在backend.properties文件中配置

  3. 注册插件, 通过ServiceLoader.load(HugeGraphPlugin.class) 加载插件

  4. 加载gremlinConfFile,并检查graphs配置项是否配置正确

  5. 针对配置的每个图,进行初始化,不同的后端存储,初始化逻辑不同,针对MySQL,主要是创建图对应的数据库及数据表

  6. 针对RestServer,初始化admin用户StandardAuthenticator.initAdminUser(restConfFile);

  7. 关闭并释放资源 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

  1. HugeRestServer 本身是启动一个glassfish应用服务器的HttpServer, 通过在构建RestServer实例时,加载配置文件new RestServer(new HugeConfig(conf));

  2. 通过构建ApplicationConfig注册componentClass,注册的componentClass详见如下代码,通过GraphManagerFactory加载配置的所有graph, WorkLoad简单的实现httpServer负载的控制,RolesAllowedDynamicFeature实现简单的权限控制(因为一些操作如顶点、边、图等操作只能admin用户操作,这类操作被@RolesAllowed 注解)

  3. 在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));
        }

     

 

上一篇:Lc222_完全二叉树的节点个数


下一篇:PHP+ajaxfileupload与jcrop插件结合 完成头像上传