跳到内容

ConfiguredGraphFactory

JanusGraph 服务器可以配置为使用 ConfiguredGraphFactoryConfiguredGraphFactory 是您图的访问点,类似于 JanusGraphFactory。这些图工厂提供了动态管理服务器上托管的图的方法。

概述

JanusGraphFactory 是一个类,通过在每次访问图时提供一个 Configuration 对象来提供您图的访问点。

ConfiguredGraphFactory 为您的图提供访问点,您之前已使用 ConfigurationManagementGraph 为这些图创建了配置。它还提供了一个访问点来管理图配置。

ConfigurationManagementGraph 允许您管理图配置。

JanusGraphManager 是一个内部服务器组件,用于跟踪图引用,前提是您的图已配置为使用它。

ConfiguredGraphFactory 与 JanusGraphFactory

然而,这两个图工厂之间存在一个重要的区别

  1. 只有在服务器启动时,您已将服务器配置为使用 ConfigurationManagementGraph API 时,才能使用 ConfiguredGraphFactory

使用 ConfiguredGraphFactory 的好处是

  1. 您只需提供一个 String 即可访问您的图,而 JanusGraphFactory 则要求您在每次打开图时指定要使用的后端信息。

  2. 如果您的 ConfigurationManagementGraph 配置了分布式存储后端,那么您的图配置将可供集群中的所有 JanusGraph 节点使用。

ConfiguredGraphFactory 如何工作?

ConfiguredGraphFactory 在两种情况下提供图的访问点

  1. 您已经使用 ConfigurationManagementGraph#createConfiguration 为您的特定图对象创建了配置。在这种情况下,您的图是使用为此图先前创建的配置打开的。

  2. 您已经使用 ConfigurationManagementGraph#createTemplateConfiguration 创建了模板配置。在这种情况下,我们通过复制存储在模板配置中的所有属性并附加相关的 graphName 属性来为正在创建的图创建配置,然后我们根据该特定配置打开图。

访问图

您可以使用 ConfiguredGraphFactory.create("graphName")ConfiguredGraphFactory.open("graphName")。要了解这两个选项之间的区别,请阅读下面关于 ConfigurationManagementGraph 的部分。

您还可以通过使用绑定来访问您的图。有关更多信息,请阅读图和遍历绑定部分。

列出图

ConfiguredGraphFactory.getGraphNames() 将返回一组图名称,您已使用 ConfigurationManagementGraph API 为这些图创建了配置。

另一方面,JanusGraphFactory.getGraphNames() 返回一组图名称,您已实例化了这些图,并且引用存储在 JanusGraphManager 中。

删除图

ConfiguredGraphFactory.drop("graphName") 将删除图数据库,删除存储和索引后端中的所有数据。图可以打开或关闭(将作为删除操作的一部分关闭)。此外,这将删除 ConfigurationManagementGraph 中任何现有的图配置。

重要

这是一项不可逆的操作,将删除所有图和索引数据。

重要

为确保集群中所有 JanusGraph 节点上的所有图表示一致,这将从集群中每个节点的 JanusGraphManager 图缓存中删除图,前提是每个节点都已正确配置为使用 JanusGraphManager。要了解有关此功能以及如何配置服务器以使用该功能的更多信息,请参阅此处

为 ConfiguredGraphFactory 配置 JanusGraph 服务器

注意

从 JanusGraph v0.6.0 开始,如果 ConfigurationManagementGraphgraphs 部分中配置并且未覆盖默认的 GraphManager,则每个 JanusGraph 服务器都将与 JanusGraphManager 一起启动。

为了能够使用 ConfiguredGraphFactory,您必须将服务器配置为使用 ConfigurationManagementGraph API。为此,您必须在服务器 YAML 的 graphs 映射中注入一个名为“ConfigurationManagementGraph”的图变量。例如

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

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

gremlin.graph=org.janusgraph.core.ConfiguredGraphFactory
storage.backend=cql
graph.graphname=ConfigurationManagementGraph
storage.hostname=127.0.0.1

假设 GremlinServer 成功启动并且 ConfigurationManagementGraph 成功实例化,那么 ConfigurationManagementGraph Singleton 上可用的所有 API 也将作用于该图。此外,这是将用于访问创建/打开图(使用 ConfiguredGraphFactory)所使用的配置的图。

重要

JanusGraph 分发版中包含的 pom.xml 将此依赖项列为可选,但 ConfiguredGraphFactory 使用 JanusGraphManager,后者需要声明对 org.apache.tinkerpop:gremlin-server 的依赖项。因此,如果您遇到 NoClassDefFoundError 错误,请务必根据此消息进行更新。

ConfigurationManagementGraph

ConfigurationManagementGraph 是一个 Singleton,它允许您创建/更新/删除配置,您可以使用这些配置通过 ConfiguredGraphFactory 访问您的图。请参阅上面关于配置服务器以启用使用这些 API 的部分。

重要

ConfiguredGraphFactory 提供了一个访问点来管理由 ConfigurationManagementGraph 管理的图配置,因此您不必作用于 Singleton 本身,您可以作用于相应的 ConfiguredGraphFactory 静态方法。例如,您可以使用 ConfiguredGraphFactory.removeTemplateConfiguration() 而不是 ConfiguredGraphFactory.getInstance().removeTemplateConfiguration()

图配置

ConfigurationManagementGraph 单例允许您创建用于打开特定图的配置,这些图由 graph.graphname 属性引用。例如

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 节点上使用以下方法访问此图

ConfiguredGraphFactory.open("graph1");

模板配置

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

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

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

ConfiguredGraphFactory.create("graph2");

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

ConfiguredGraphFactory.open("graph2");

更新配置

JanusGraphFactoryConfiguredGraphFactory 的所有交互,如果它们与定义属性 graph.graphname 的配置进行交互,都将通过 JanusGraphManager,后者跟踪在给定 JVM 上创建的图引用。将其视为图缓存。因此

重要

对图配置的任何更新都会导致相关图从 JanusGraph 集群中每个节点上的图缓存中逐出,前提是每个节点都已正确配置为使用 JanusGraphManager。要了解有关此功能以及如何配置服务器以使用该功能的更多信息,请参阅此处

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

重要

在使用模板配置创建的特定图的任何更新都不能保证在该特定图上生效,直到:1. 相关配置被删除:ConfiguredGraphFactory.removeConfiguration("graph2"); 2. 图使用模板配置重新创建:ConfiguredGraphFactory.create("graph2");

更新示例

1) 我们将 Cassandra 数据迁移到具有新 IP 地址的新服务器

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",
new MapConfiguration(map));

// We can verify the configuration was updated by
// retrieving the configuration for this graph
ConfiguredGraphFactory.getConfiguration("graph1");

// We are now guaranteed to use the updated configuration
g1 = ConfiguredGraphFactory.open("graph1");

2) 我们在设置中添加了一个 Elasticsearch 节点

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",
new MapConfiguration(map));

// We can verify the configuration was updated by
// retrieving the configuration for this graph
ConfiguredGraphFactory.getConfiguration("graph1");

// We are now guaranteed to use the updated configuration
g1 = ConfiguredGraphFactory.open("graph1");

3) 更新使用已更新的模板配置创建的图配置

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.
// We can verify it by retrieving the configuration for this graph
ConfiguredGraphFactory.getConfiguration("graph1");

JanusGraphManager

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

特别是,JanusGraphManager 提供

  1. 一种协调机制,用于在给定 JanusGraph 节点上实例化图引用

  2. 图引用跟踪器(或缓存)

您使用 graph.graphname 属性创建的任何图都将通过 JanusGraphManager,因此将以协调的方式实例化。图引用也将放置在相关 JVM 上的图缓存中。

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

这就是为什么更新配置需要几个步骤才能保证正确性。

如何使用 JanusGraphManager

这是一个新的配置选项,您可以在定义配置中定义如何访问图的属性时使用。所有包含此属性的配置都将导致图实例化通过 JanusGraphManager 进行(如上所述)。

为了向后兼容,任何未提供此参数但在服务器启动时在 .yaml 文件中的图对象中提供的图,这些图将通过 JanusGraphManager 绑定,由为该图提供的 key 表示。例如,如果您的 .yaml 图对象如下所示

graphManager: org.janusgraph.graphdb.management.JanusGraphManager
graphs {
  graph1: conf/graph1.properties,
  graph2: conf/graph2.properties
}

conf/graph1.propertiesconf/graph2.properties 不包含属性 graph.graphname,那么这些图将存储在 JanusGraphManager 中,并因此在您的 gremlin 脚本执行中分别绑定为 graph1graph2

后端图的自动分离

为方便起见,如果用于打开图的配置指定了 graph.graphname,但未指定后端存储目录、表名、键空间名或索引名,则相关参数将自动设置为 graph.graphname 的值。但是,如果您提供其中一个参数,该值将始终优先。如果您两者都不提供,它们将默认为配置选项的默认值。

一个特殊情况是 storage.root 配置选项。这是一个新的配置选项,用于指定将用于任何需要本地存储目录访问的后端的基础目录。如果您提供此参数,您还必须提供 graph.graphname 属性,并且绝对存储目录将等于 graph.graphname 属性的值附加到 storage.root 属性的值。

下面是一些示例用例

1) 为我的 Cassandra 后端创建一个模板配置,以便使用此配置创建的每个图都获得一个唯一的键空间,等同于提供给工厂的 String <graphName>

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

2) 为我的 BerkeleyJE 后端创建一个模板配置,以便使用此配置创建的每个图都获得一个唯一的存储目录,等同于“<storage.root>/<graph.graphname>”

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

图和遍历绑定

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

要了解有关此功能以及如何配置服务器以使用该功能的更多信息,请参阅此处

重要

如果您使用 Gremlin Console 和 会话式 连接连接到远程 Gremlin Server,那么您必须重新连接到服务器才能绑定变量。对于任何会话式 WebSocket 连接也是如此。

重要

JanusGraphManager 每 20 秒重新绑定存储在 ConfigurationManagementGraph 上的每个图(或您已创建配置的图)。这意味着使用 ConfiguredGraphFactory 创建的图的图和遍历绑定将在所有 JanusGraph 节点上可用,最大延迟为 20 秒。这也意味着在服务器重新启动后,绑定仍将在节点上可用。

绑定示例

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[cql:[127.0.0.1]]
gremlin> graph1
==>standardjanusgraph[cql:[127.0.0.1]]
gremlin> graph1_traversal
==>graphtraversalsource[standardjanusgraph[cql:[127.0.0.1]], standard]

示例

建议在创建配置图工厂模板时使用会话式连接。如果未使用会话式连接,则配置图工厂模板创建必须使用分号作为单行发送到服务器。有关会话的详细信息,请参阅连接到 Gremlin Server

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