HugeGraph Plugin机制及插件扩展流程

背景

  1. HugeGraph不仅开源开放,而且要做到简单易用,一般用户无需更改源码也能轻松增加插件扩展功能。
  2. HugeGraph支持多种内置存储后端,也允许用户无需更改现有源码的情况下扩展自定义后端。
  3. HugeGraph支持全文检索,全文检索功能涉及到各语言分词,目前已内置8种中文分词器,也允许用户无需更改现有源码的情况下扩展自定义分词器。

可扩展维度

目前插件方式提供如下几个维度的扩展项:

  • 后端存储
  • 序列化器
  • 自定义配置项
  • 分词器

插件实现机制

  1. HugeGraph提供插件接口HugeGraphPlugin,通过Java SPI机制支持插件化
  2. HugeGraph提供了4个扩展项注册函数:registerOptions()registerBackend()registerSerializer()registerAnalyzer()
  3. 插件实现者实现相应的Options、Backend、Serializer或Analyzer的接口
  4. 插件实现者实现HugeGraphPlugin接口的register()方法,在该方法中注册上述第3点所列的具体实现类,并打成jar包
  5. 插件使用者将jar包放在HugeGraph Server安装目录的plugins目录下,修改相关配置项为插件自定义值,重启即可生效

插件实现流程实例

1 新建一个maven项目

1.1 项目名称取名:hugegraph-plugin-demo
1.2 添加hugegraph-core Jar包依赖

maven pom.xml详细内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.baidu.hugegraph</groupId>
  7. <artifactId>hugegraph-plugin-demo</artifactId>
  8. <version>1.0.0</version>
  9. <packaging>jar</packaging>
  10. <name>hugegraph-plugin-demo</name>
  11. <dependencies>
  12. <dependency>
  13. <groupId>com.baidu.hugegraph</groupId>
  14. <artifactId>hugegraph-core</artifactId>
  15. <version>${project.version}</version>
  16. </dependency>
  17. </dependencies>
  18. </project>

2 实现扩展功能

2.1 扩展自定义后端
2.1.1 实现接口BackendStoreProvider
  • 可实现接口:com.baidu.hugegraph.backend.store.BackendStoreProvider
  • 或者继承抽象类:com.baidu.hugegraph.backend.store.AbstractBackendStoreProvider

以RocksDB后端RocksDBStoreProvider为例:

  1. public class RocksDBStoreProvider extends AbstractBackendStoreProvider {
  2. protected String database() {
  3. return this.graph().toLowerCase();
  4. }
  5. @Override
  6. protected BackendStore newSchemaStore(String store) {
  7. return new RocksDBSchemaStore(this, this.database(), store);
  8. }
  9. @Override
  10. protected BackendStore newGraphStore(String store) {
  11. return new RocksDBGraphStore(this, this.database(), store);
  12. }
  13. @Override
  14. public String type() {
  15. return "rocksdb";
  16. }
  17. @Override
  18. public String version() {
  19. return "1.0";
  20. }
  21. }
2.1.2 实现接口BackendStore

BackendStore接口定义如下:

  1. public interface BackendStore {
  2. // Store name
  3. public String store();
  4. // Database name
  5. public String database();
  6. // Get the parent provider
  7. public BackendStoreProvider provider();
  8. // Open/close database
  9. public void open(HugeConfig config);
  10. public void close();
  11. // Initialize/clear database
  12. public void init();
  13. public void clear();
  14. // Add/delete data
  15. public void mutate(BackendMutation mutation);
  16. // Query data
  17. public Iterator<BackendEntry> query(Query query);
  18. // Transaction
  19. public void beginTx();
  20. public void commitTx();
  21. public void rollbackTx();
  22. // Get metadata by key
  23. public <R> R metadata(HugeType type, String meta, Object[] args);
  24. // Backend features
  25. public BackendFeatures features();
  26. // Generate an id for a specific type
  27. public Id nextId(HugeType type);
  28. }
2.1.3 扩展自定义序列化器

序列化器必须继承抽象类:com.baidu.hugegraph.backend.serializer.AbstractSerializer(implements GraphSerializer, SchemaSerializer)主要接口的定义如下:

  1. public interface GraphSerializer {
  2. public BackendEntry writeVertex(HugeVertex vertex);
  3. public BackendEntry writeVertexProperty(HugeVertexProperty<?> prop);
  4. public HugeVertex readVertex(HugeGraph graph, BackendEntry entry);
  5. public BackendEntry writeEdge(HugeEdge edge);
  6. public BackendEntry writeEdgeProperty(HugeEdgeProperty<?> prop);
  7. public HugeEdge readEdge(HugeGraph graph, BackendEntry entry);
  8. public BackendEntry writeIndex(HugeIndex index);
  9. public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, BackendEntry entry);
  10. public BackendEntry writeId(HugeType type, Id id);
  11. public Query writeQuery(Query query);
  12. }
  13. public interface SchemaSerializer {
  14. public BackendEntry writeVertexLabel(VertexLabel vertexLabel);
  15. public VertexLabel readVertexLabel(HugeGraph graph, BackendEntry entry);
  16. public BackendEntry writeEdgeLabel(EdgeLabel edgeLabel);
  17. public EdgeLabel readEdgeLabel(HugeGraph graph, BackendEntry entry);
  18. public BackendEntry writePropertyKey(PropertyKey propertyKey);
  19. public PropertyKey readPropertyKey(HugeGraph graph, BackendEntry entry);
  20. public BackendEntry writeIndexLabel(IndexLabel indexLabel);
  21. public IndexLabel readIndexLabel(HugeGraph graph, BackendEntry entry);
  22. }
2.1.4 扩展自定义配置项

增加自定义后端时,可能需要增加新的配置项,实现流程主要包括:

  • 增加配置项容器类,并实现接口com.baidu.hugegraph.config.OptionHolder
  • 提供单例方法public static OptionHolder instance(),并在对象初始化时调用方法OptionHolder.registerOptions()
  • 增加配置项声明,单值配置项类型为ConfigOption、多值配置项类型为ConfigListOption

以RocksDB配置项定义为例:

  1. public class RocksDBOptions extends OptionHolder {
  2. private RocksDBOptions() {
  3. super();
  4. }
  5. private static volatile RocksDBOptions instance;
  6. public static synchronized RocksDBOptions instance() {
  7. if (instance == null) {
  8. instance = new RocksDBOptions();
  9. instance.registerOptions();
  10. }
  11. return instance;
  12. }
  13. public static final ConfigOption<String> DATA_PATH =
  14. new ConfigOption<>(
  15. "rocksdb.data_path",
  16. "The path for storing data of RocksDB.",
  17. disallowEmpty(),
  18. "rocksdb-data"
  19. );
  20. public static final ConfigOption<String> WAL_PATH =
  21. new ConfigOption<>(
  22. "rocksdb.wal_path",
  23. "The path for storing WAL of RocksDB.",
  24. disallowEmpty(),
  25. "rocksdb-data"
  26. );
  27. public static final ConfigListOption<String> DATA_DISKS =
  28. new ConfigListOption<>(
  29. "rocksdb.data_disks",
  30. false,
  31. "The optimized disks for storing data of RocksDB. " +
  32. "The format of each element: `STORE/TABLE: /path/to/disk`." +
  33. "Allowed keys are [graph/vertex, graph/edge_out, graph/edge_in, " +
  34. "graph/secondary_index, graph/range_index]",
  35. null,
  36. String.class,
  37. ImmutableList.of()
  38. );
  39. }
2.2 扩展自定义分词器

分词器需要实现接口com.baidu.hugegraph.analyzer.Analyzer,以实现一个SpaceAnalyzer空格分词器为例。

  1. package com.baidu.hugegraph.plugin;
  2. import java.util.Arrays;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. import com.baidu.hugegraph.analyzer.Analyzer;
  6. public class SpaceAnalyzer implements Analyzer {
  7. @Override
  8. public Set<String> segment(String text) {
  9. return new HashSet<>(Arrays.asList(text.split(" ")));
  10. }
  11. }

3 实现插件接口,并进行注册

插件注册入口为HugeGraphPlugin.register(),自定义插件必须实现该接口方法,在其内部注册上述定义好的扩展项。接口com.baidu.hugegraph.plugin.HugeGraphPlugin定义如下:

  1. public interface HugeGraphPlugin {
  2. public String name();
  3. public void register();
  4. public String supportsMinVersion();
  5. public String supportsMaxVersion();
  6. }

并且HugeGraphPlugin提供了4个静态方法用于注册扩展项:

  • registerOptions(String name, String classPath):注册配置项
  • registerBackend(String name, String classPath):注册后端(BackendStoreProvider)
  • registerSerializer(String name, String classPath):注册序列化器
  • registerAnalyzer(String name, String classPath):注册分词器

下面以注册SpaceAnalyzer分词器为例:

  1. package com.baidu.hugegraph.plugin;
  2. public class DemoPlugin implements HugeGraphPlugin {
  3. @Override
  4. public String name() {
  5. return "demo";
  6. }
  7. @Override
  8. public void register() {
  9. HugeGraphPlugin.registerAnalyzer("demo", SpaceAnalyzer.class.getName());
  10. }
  11. }

4 配置SPI入口

  1. 确保services目录存在:hugegraph-plugin-demo/resources/META-INF/services
  2. 在services目录下建立文本文件:com.baidu.hugegraph.plugin.HugeGraphPlugin
  3. 文件内容如下:com.baidu.hugegraph.plugin.DemoPlugin

5 打Jar包

通过maven打包,在项目目录下执行命令mvn package,在target目录下会生成Jar包文件。使用时将该Jar包拷到plugins目录,重启服务即可生效。