可以使用ConfiguredGraphFactory去配置JanusGraph Server。 ConfiguredGraphFactory是图的一种访问方式,类似于JanusGraphFactory。 这些图的工厂类提供了动态管理托管在服务器上的图的方法。

1. 概述

JanusGraphFactory是一个类,它提供了一种图的访问方式,每次通过配置Configuration对象来访问你的图。

ConfiguredGraphFactory提供了一种访问你使用ConfigurationManagementGraph创建配置的图的方式。 它还提供了一种方式去管理图的配置。

ConfigurationManagementGraph允许你去管理图的配置。

JanusGraphManager是一个内部服务组件,可以跟踪图的引用,前提是你的图是使用它配置的。

2. ConfiguredGraphFactory 与 JanusGraphFactory

但是,这两个图工厂类之间存在一个重要区别:

  • 只有在服务启动时你已经使用ConfigurationManagementGraph API来配置你的server了,ConfiguredGraphFactory才能被使用。

使用ConfiguredGraphFactory的好处是:

  • 你只需要提供一个String来访问你的图,而不是JanusGraphFactory—它要求你在每次打开图时都要指定在访问图形时要使用的后端信息。
  • 如果你的ConfigurationManagementGraph配置了分布式存储后端,则你的图配置可供群集中的所有JanusGraph节点使用。

3. ConfiguredGraphFactory如何工作

ConfiguredGraphFactory在以下两种情况下提供图访问方式:

  • 你已使用ConfigurationManagementGraph#createConfiguration为特定图对象创建了配置。 在此方案中,使用先前为此图创建的配置打开图。
  • 你已使用ConfigurationManagementGraph#createTemplateConfiguration创建了模板配置。 在这种情况下,我们通过复制存储在模板配置中的所有属性并附加相关的graphName属性来为你创建的图创建配置,然后根据该特定配置打开图。

4. 图的访问

你可以使用ConfiguredGraphFactory.create(“graphName”)或ConfiguredGraphFactory.open(“graphName”)。 阅读以下有关ConfigurationManagementGraph的部分,了解这两种方式更多的不同之处。

你还可以使用绑定来访问图。 有关详细信息,请参见第9.10节“Graph and Traversal Bindings”部分。

5. 图的列表

ConfiguredGraphFactory.getGraphNames()将返回一组你使用ConfigurationManagementGraph API为其创建配置的图的名称,。

另一方面,JanusGraphFactory.getGraphNames()返回一组你实例化的图的名称,而且引用存储在JanusGraphManager中。

6. 图的删除

ConfiguredGraphFactory.drop(“graphName”)将删除图数据库,删除存储和索引中的所有数据。 这个图可以是打开的或着关闭的(将被关闭作为删除操作的一部分)。 此外,它还将删除ConfigurationManagementGraph中的任何已有图配置。

注意:

  • 这是一个不可逆转的操作,它将删除所有的图和索引数据。
  • 假设每个节点都以正确的配置去使用JanusGraphManager,以确保集群中所有JanusGraph节点的所有图表示都是一致的,这将从集群中每个节点上的JanusGraphManager图形缓存中删除图。 详细了解此功能以及如何配置服务以使用此功能。

7. 为ConfiguredGraphFactory配置JanusGraph服务

为了使用ConfiguredGraphFactory,你必须使用ConfigurationManagementGraph API来配置你的服务。 为此,你必须在你的服务的YAML文件的graphs中配置名为“ConfigurationManagementGraph”的图变量。 例如:

1
2
3
4
graphManager: org.janusgraph.graphdb.management.JanusGraphManager
graphs: {
ConfigurationManagementGraph: conf/JanusGraph-configurationmanagement.properties
}

在此示例中,我们的ConfigurationManagementGraph图将使用conf/JanusGraph-configurationmanagement.properties中存储的属性进行配置,例如,如下所示:

1
2
3
4
gremlin.graph=org.janusgraph.core.JanusGraphFactory
storage.backend=cql
graph.graphname=ConfigurationManagementGraph
storage.hostname=127.0.0.1

如果GremlinServer启动成功而且ConfigurationManagementGraph被成功实例化,则ConfigurationManagementGraph Singleton上的所有可用API也将对所述图执行操作。 此外,这个图可以使用ConfiguredGraphFactory的create/open来访问图的配置。

注意:

JanusGraph发行版中包含的pom.xml将此依赖项列为可选项,但ConfiguredGraphFactory使用了JanusGraphManager,它需要依赖org.apache.tinkerpop:gremlin-server。 因此,如果你遇到NoClassDefFoundError错误,请务必根据此提示在pom.xml中添加依赖。

8. ConfigurationManagementGraph

ConfigurationManagementGraph是一个Singleton,允许你使用ConfiguredGraphFactory create/update/remove 图的配置。 请参阅上文有关配置服务以使用这些API。

注意:ConfiguredGraphFactory提供了一个通过ConfigurationManagementGraph来管理图配置的方法,因此你可以使用相应的ConfiguredGraphFactory静态方法,而不是对单例本身进行操作。 例如,你可以使用ConfiguredGraphFactory.removeTemplateConfiguration()而不是ConfiguredGraphFactory.getInstance().removeTemplateConfiguration()。

8.1. 图的配置

ConfigurationManagementGraph单例允许你通过graph.graphname属性来创建用于打开特定图的配置。 例如:

1
2
3
4
5
map = new HashMap<String, Object>();
map.put("storage.backend", "cql");
map.put("storage.hostname", "127.0.0.1");
map.put("graph.graphname", "graph1");
ConfiguredGraphFactory.createConfiguration(new MapConfiguration(map));

然后,你可以使用以下方式在任何JanusGraph节点上访问此图:

1
ConfiguredGraphFactory.open("graph1");
8.2. 模板配置

ConfigurationManagementGraph还允许你创建一个模板配置,你可以使用相同的配置模板创建许多图。 例如:

1
2
3
4
map = new HashMap<String, Object>();
map.put("storage.backend", "cql");
map.put("storage.hostname", "127.0.0.1");
ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));

完成此操作后,你可以使用模板配置创建图:

1
ConfiguredGraphFactory.create("graph2");

此方法将首先通过复制与模板配置关联的所有属性并将其存储在此特定图的配置上来为“graph2”创建新配置。 这意味着可以通过以下方式在任何JanusGraph节点上访问此图:

1
ConfiguredGraphFactory.open("graph2");
8.3. 更新配置

与JanusGraphFactory和ConfiguredGraphFactory的所有交互都与定义属性graph.graphname的配置交互,通过JanusGraphManager跟踪在给定JVM上创建的图引用。 将其视为图形缓存。 为此原因:

对图配置的任何更新都会导致从JanusGraph集群中每个节点上的图缓存中逐出相关图形,假设每个节点都已正确配置以使用JanusGraphManager。 详细了解此功能以及如何配置服务器以使用此功能。

由于使用模板配置创建的图形首先使用复制和创建方法为该图形创建配置,这意味着:

对使用模板配置创建的特定图表的任何更新都不能保证在特定图表上生效,直到:

  1. 删除相关配置:ConfiguredGraphFactory.removeConfiguration(“graph2”);
  2. 使用模板配置重新创建图:ConfiguredGraphFactory.create(“graph2”);
8.4. 更新示例
  1. 我们将Cassandra数据迁移到具有新IP地址的新服务器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    map = new HashMap();
    map.put("storage.backend", "cql");
    map.put("storage.hostname", "127.0.0.1");
    map.put("graph.graphname", "graph1");
    ConfiguredGraphFactory.createConfiguration(new
    MapConfiguration(map));

    g1 = ConfiguredGraphFactory.open("graph1");

    // Update configuration
    map = new HashMap();
    map.put("storage.hostname", "10.0.0.1");
    ConfiguredGraphFactory.updateConfiguration("graph1",
    map);

    // We are now guaranteed to use the updated configuration
    g1 = ConfiguredGraphFactory.open("graph1");
  2. 我们在设置中添加了一个Elasticsearch节点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    map = new HashMap();
    map.put("storage.backend", "cql");
    map.put("storage.hostname", "127.0.0.1");
    map.put("graph.graphname", "graph1");
    ConfiguredGraphFactory.createConfiguration(new
    MapConfiguration(map));

    g1 = ConfiguredGraphFactory.open("graph1");

    // Update configuration
    map = new HashMap();
    map.put("index.search.backend", "elasticsearch");
    map.put("index.search.hostname", "127.0.0.1");
    map.put("index.search.elasticsearch.transport-scheme", "http");
    ConfiguredGraphFactory.updateConfiguration("graph1",
    map);

    // We are now guaranteed to use the updated configuration
    g1 = ConfiguredGraphFactory.open("graph1");
  3. 更新使用已更新的模板配置创建的图形配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    map = new HashMap();
    map.put("storage.backend", "cql");
    map.put("storage.hostname", "127.0.0.1");
    ConfiguredGraphFactory.createTemplateConfiguration(new
    MapConfiguration(map));

    g1 = ConfiguredGraphFactory.create("graph1");

    // Update template configuration
    map = new HashMap();
    map.put("index.search.backend", "elasticsearch");
    map.put("index.search.hostname", "127.0.0.1");
    map.put("index.search.elasticsearch.transport-scheme", "http");
    ConfiguredGraphFactory.updateTemplateConfiguration(new
    MapConfiguration(map));

    // Remove Configuration
    ConfiguredGraphFactory.removeConfiguration("graph1");

    // Recreate
    ConfiguredGraphFactory.create("graph1");
    // Now this graph's configuration is guaranteed to be updated

    9. JanusGraphManager

    JanusGraphManager是一个遵循TinkerPop graphManager规范的Singleton。

    特别是,JanusGraphManager提供:

    • 一种协调机制,用于在给定的JanusGraph节点上实例化图引用
    • 图形参考跟踪器(或缓存)

    使用graph.graphname属性创建的任何图形都将通过JanusGraphManager,以相应的方式实例化。 图表引用也将存储在JVM上的图缓存中。

    因此,使用graph.graphname属性打开的,在相关JVM上实例化的任何图将从图缓存中检索。

    这就是为什么更新配置需要几个步骤来保证正确性的原因。

    9.1. 怎么使用JanusGraphManager

    这是在配置中定义属性时可以使用的新配置选项,用于定义如何访问图形。 包含此属性的所有配置都将导致图形实例化通过JanusGraphManager(上面解释的过程)实现。

    为了向后兼容,任何不支持此参数但在服务器上提供的图形都在.yaml文件中的graph对象中启动,这些图将通过为该图提供的键表示的JanusGraphManager进行绑定。 例如,如果您的.yaml图对象如下所示:

    1
    2
    3
    4
    5
    graphManager: org.janusgraph.graphdb.management.JanusGraphManager
    graphs {
    graph1: conf/graph1.properties,
    graph2: conf/graph2.properties
    }

    但是conf / graph1.properties和conf / graph2.properties都不包含属性graph.graphname,那么这些图将存储在JanusGraphManager中,因此分别作为graph1和graph2绑定在gremlin脚本执行中。

    9.2. 注意

    为方便起见,如果你的配置文件中指定了graph.graphname,但未配置后端存储的目录,tablename或keyspacename,则相关参数将自动设置为graph.graphname的值。 但是,如果你配置了其中一个参数,则优先使用该值。 如果你没有配置,则默认为配置项使用默认值。

    一个特例是storage.root的配置项。 这是一个新的配置项,用于指定将用于需要本地存储目录访问的任何后端目录的根目录。 如果提供此参数,则还必须提供graph.graphname属性,这个绝对存储目录将是storage.root路径加上graph.graphname路径。

    以下是一些使用示例:

    • 为我的Cassandra后端创建模板配置,以便使用此配置创建的每个图形获得与提供给工厂方法的String <graphName>等效的唯一键空间:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      map = new HashMap();
      map.put("storage.backend", "cql");
      map.put("storage.hostname", "127.0.0.1");
      ConfiguredGraphFactory.createTemplateConfiguration(new
      MapConfiguration(map));

      g1 = ConfiguredGraphFactory.create("graph1"); //keyspace === graph1
      g2 = ConfiguredGraphFactory.create("graph2"); //keyspace === graph2
      g3 = ConfiguredGraphFactory.create("graph3"); //keyspace === graph3
    • 为我的BerkeleyJE后端创建模板配置,以便使用此配置创建的每个图形都获得一个等同于<storage.root> / <graph.graphname>的唯一存储目录:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      map = new HashMap();
      map.put("storage.backend", "berkeleyje");
      map.put("storage.root", "/data/graphs");
      ConfiguredGraphFactory.createTemplateConfiguration(new
      MapConfiguration(map));

      g1 = ConfiguredGraphFactory.create("graph1"); //storage directory === /data/graphs/graph1
      g2 = ConfiguredGraphFactory.create("graph2"); //storage directory === /data/graphs/graph2
      g3 = ConfiguredGraphFactory.create("graph3"); //storage directory === /data/graphs/graph3

    10. Graph and Traversal Bindings

    使用ConfiguredGraphFactory创建的图形通过“graph.graphname”属性绑定到Gremlin Server上的执行程序上下文,并且图形的遍历引用通过<graphname> _traversal绑定到上下文。 这意味着,在第一次创建/打开图形后,在后续连接到服务器时,你可以通过<graphname><graphname> _traversal属性访问图形和遍历引用。

    详细了解此功能以及如何配置服务器以使用此功能。

    注意:

    • 如果使用Gremlin控制台和会话连接连接到远程Gremlin服务器,则必须重新连接到服务器以绑定变量。 对于任何会话的WebSocket连接也是如此。
    • JanusGraphManager每20秒重新绑定存储在ConfigurationManagementGraph(或你已创建配置的图形)上的每个图形。 这意味着使用ConfigredGraphFactory创建的图形和遍历绑定将在所有JanusGraph节点上可用,最多延迟20秒。 它还意味着在服务器重新启动后,节点上的binding仍然可以使用。
    10.1 Binding Example
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    gremlin> :remote connect tinkerpop.server conf/remote.yaml
    ==>Configured localhost/127.0.0.1:8182
    gremlin> :remote console
    ==>All scripts will now be sent to Gremlin Server - [localhost/127.0.0.1:8182] - type ':remote console' to return to local mode
    gremlin> ConfiguredGraphFactory.open("graph1")
    ==>standardjanusgraph[cassandrathrift:[127.0.0.1]]
    gremlin> graph1
    ==>standardjanusgraph[cassandrathrift:[127.0.0.1]]
    gremlin> graph1_traversal
    ==>graphtraversalsource[standardjanusgraph[cassandrathrift:[127.0.0.1]], standard]

    11. 示例

    建议在创建Configured Graph Factory模板时使用会话连接。 如果未使用会话连接,则必须使用分号将配置的图形工厂模板创建作为单行发送到服务器。 有关会话的详细信息,请参见第7.1.1.1节“连接到Gremlin Server”。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    gremlin> :remote connect tinkerpop.server conf/remote.yaml session
    ==>Configured localhost/127.0.0.1:8182

    gremlin> :remote console
    ==>All scripts will now be sent to Gremlin Server - [localhost:8182]-[5206cdde-b231-41fa-9e6c-69feac0fe2b2] - type ':remote console' to return to local mode

    gremlin> ConfiguredGraphFactory.open("graph");
    Please create configuration for this graph using the
    ConfigurationManagementGraph API.

    gremlin> ConfiguredGraphFactory.create("graph");
    Please create a template Configuration using the
    ConfigurationManagementGraph API.

    gremlin> map = new HashMap();
    gremlin> map.put("storage.backend", "cql");
    gremlin> map.put("storage.hostname", "127.0.0.1");
    gremlin> map.put("GraphName", "graph1");
    gremlin> ConfiguredGraphFactory.createConfiguration(new MapConfiguration(map));
    Please include in your configuration the property "graph.graphname".

    gremlin> map = new HashMap();
    gremlin> map.put("storage.backend", "cql");
    gremlin> map.put("storage.hostname", "127.0.0.1");
    gremlin> map.put("graph.graphname", "graph1");
    gremlin> ConfiguredGraphFactory.createConfiguration(new MapConfiguration(map));
    ==>null

    gremlin> ConfiguredGraphFactory.open("graph1").vertices();

    gremlin> map = new HashMap(); map.put("storage.backend",
    "cql"); map.put("storage.hostname", "127.0.0.1");
    gremlin> map.put("graph.graphname", "graph1");
    gremlin> ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));
    Your template configuration may not contain the property
    "graph.graphname".

    gremlin> map = new HashMap();
    gremlin> map.put("storage.backend",
    "cql"); map.put("storage.hostname", "127.0.0.1");
    gremlin> ConfiguredGraphFactory.createTemplateConfiguration(new MapConfiguration(map));
    ==>null

    // Each graph is now acting in unique keyspaces equivalent to the
    graphnames.
    gremlin> g1 = ConfiguredGraphFactory.open("graph1");
    gremlin> g2 = ConfiguredGraphFactory.create("graph2");
    gremlin> g3 = ConfiguredGraphFactory.create("graph3");
    gremlin> g2.addVertex();
    gremlin> l = [];
    gremlin> l << g1.vertices().size();
    ==>0
    gremlin> l << g2.vertices().size();
    ==>1
    gremlin> l << g3.vertices().size();
    ==>0

    // After a graph is created, you must access it using .open()
    gremlin> g2 = ConfiguredGraphFactory.create("graph2"); g2.vertices().size();
    Configuration for graph "graph2" already exists.

    gremlin> g2 = ConfiguredGraphFactory.open("graph2"); g2.vertices().size();
    ==>1

欢迎扫码关注公众号,更好的交流
欢迎扫码关注公众号,更好的交流