跳转到主要内容

1 - HugeGraph (OLTP)

本目录包含 HugeGraph Server 单机快速上手,以及分布式部署所需的 PD 和 Store 入门文档。

DeepWiki 项目概览;涉及安装、配置和运行行为时,请以对应版本的 HugeGraph 文档及代码为准。

首次使用可从 Server 单机快速上手 开始。该页将 ASF 已发布的 1.7.0 下载包与 master 源码构建分开说明。若使用 HStore 分布式存储,还需配置 PD 和 Store。

GitHub 访问: https://github.com/apache/hugegraph

1.1 - HugeGraph Server 快速上手

1 HugeGraph Server 概述

apache/hugegraph 是 HugeGraph 图数据库的主仓库,包含 hugegraph-server、hugegraph-pd、hugegraph-store 等一级模块。本页介绍其中的 hugegraph-server 模块及其运行服务。

hugegraph-server 模块包含 hugegraph-core、hugegraph-api、hugegraph-dist 和存储适配等子模块。Core 实现属性图模型、事务与 TinkerPop 接口,API 提供 HTTP 服务并将客户端请求交给 Core 处理。图数据由 RocksDB(单机默认)、HStore(分布式)或 HBase 后端保存。

警告

版本说明:本文区分已发布版本与开发主线。下载示例使用 ASF 发布的 HugeGraph 1.7.0 安装包;源码构建、配置默认值和启动行为以 apache/hugegraph 的 master 分支为准。主线源码构建出的包不是 ASF 发布包,即使包内版本号与发布版本一致也不代表属于官方发布包。本文介绍 RocksDB、HStore 和 HBase;其他旧后端请参考 HugeGraph 1.5.x 文档。

名称说明:HugeGraph 表示整个项目或主仓库,hugegraph-server 表示仓库中的 Server 模块,HugeGraphServer 是服务进程的 Java 类名。下文的 Server 服务指运行中的图数据库服务。

flowchart TD
    A{选择安装来源}
    A -->|已发布版本| R["HugeGraph 1.7.0 tar 包"]
    R --> V[SHA-512 校验]
    V --> X[解压并使用随包配置]
    A -->|开发主线| M["master 源码"]
    M --> B["mvn package -DskipTests"]
    B --> C[确认 conf/graphs 中的 RocksDB 配置]
    C --> I[bin/init-store.sh]
    I --> S["bin/start-hugegraph.sh -p true"]
    S --> Q["请求 /versions 和图顶点接口"]

主仓库模块概览使用短名称;server、core、api、dist、pd 和 store 对应带 hugegraph- 前缀的模块。上方保留功能说明,dist 负责发行打包。

---
markmap:
  spacingHorizontal: 40
---
# HugeGraph
## server
- core
- api
- dist
## pd
## store

2 依赖

2.1 安装 Java 17 (JDK 17)

从 HugeGraph 1.8.0 开始使用 Java 17;1.7.0 是最后一个支持 Java 11 的版本。 所有模块的源码构建要求 JDK 17 和 Maven 3.6.3 或更高版本,Server、PD 和 Store 的运行环境统一使用 JDK 17。 Server 安全检查(-s true)要求 Java 17 到 23 以及可读的 conf/java-security.properties;在 Java 24 或更高版本上,需以 -s false 启动 Server(JDK 24 通过 JEP 486 移除了 Security Manager)。

在继续阅读前,请先执行 java -version 命令确认 JDK 版本。

说明

TinkerPop 3.8.1 兼容性与核心变更

HugeGraph 1.8.0 升级至 TinkerPop 3.8.1 与 Groovy 4.0.25。请使用 Server 随包提供的 Gremlin 配置文件。

  • 序列化器包路径变更:Driver 序列化器类从 org.apache.tinkerpop.gremlin.driver.ser 移至 org.apache.tinkerpop.gremlin.util.ser,需保留配置中的 HugeGraph registries。
  • Graph.Features 调整:supportsUniformListValues() 现返回 false;按 Schema 定义的 valueList()/LIST 属性仍正常支持,无需重写既有列表数据。
  • 遍历倍数语义:遍历中途扫描保留上游输入数量(如 3 个顶点执行 g.V().V().count() 返回 9L)。
  • 日期时间类型:DATE 属性支持写入及索引等值/范围查询中的 OffsetDateTime(按 instant 毫秒归一化)。
  • 过滤与优化:P.typeOf() 作为本地过滤执行;Count 过滤仅在谓词分支可证明截断安全时应用优化。
GraphBinary (推荐/默认)
1# 随包 Driver 与 Console 默认采用 GraphBinary V1
2# - Schema 结果为标准 Map
3# - Blob 值以二进制格式传输(包含在返回图元素内的 Blob)
4serializer:
5  className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1
6  config:
7    builder: org.apache.hugegraph.io.HugeGraphTypeSerializerRegistryBuilder
8    ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
GraphSON (HTTP/兼容)
1# 默认 HTTP JSON 采用 untyped GraphSON V1
2# - 保留 Tree 的旧 key/value 数组结构
3# - Typed GraphSON V1 因安全原因已禁用(typed V2/V3 仅适用于受支持的简单标量与 ID)
4# - graph.schema() 返回包含各类 label 的 Map
提示

完整客户端配置与验证细节见 Server 运行时文档。

3 部署

有四种方式可以部署 Server 服务:

警告

生产环境必须启用鉴权并限制网络访问

HugeGraph 默认不启用用户认证。生产环境必须启用认证与授权、启用并维护 IP 白名单,并按最小权限为用户授权;不得将 Gremlin、Cypher 等查询接口直接暴露到公网。必须保留并限制读取 Server 标准配置生成的 audit-*.log。auth.audit_log_rate 只限制每用户日志输出速率,不是审计日志的启停开关。部署安全要求见安全指南。

3.1 使用 Docker 容器 (便于测试)

可参考 Docker 部署方式。

可以使用 docker run -itd --name=server -p 8080:8080 -e PASSWORD=xxx hugegraph/hugegraph:1.7.0 快速启动一个使用 RocksDB 后端的 Server 实例。

可选项:

  1. 可以使用 docker exec -it server bash 进入容器执行运维或调试操作。
  2. 可以使用 docker run -itd --name=server -p 8080:8080 -e PRELOAD="true" hugegraph/hugegraph:1.7.0 在启动时预加载一个内置样例图。可通过 RESTful API 进行验证,具体步骤可参考 5.1.4。
  3. 可以使用 -e PASSWORD=xxx 开启鉴权模式并设置 admin 密码,具体步骤可参考 Config Authentication。

如果使用 Docker Desktop,则可以按如下方式设置相关选项:

Docker Desktop 中 HugeGraph 容器的运行设置
说明

Docker Compose 文件使用桥接网络(hg-net),适用于 Linux 和 Mac(Docker Desktop)。如需运行 3 节点分布式集群,请为 Docker Desktop 分配至少 12 GB 内存(设置 → 资源 → 内存)。Linux 上 Docker 直接使用宿主机内存。

如果希望通过一个配置文件统一管理 HugeGraph 的多个服务实例,则可以使用 docker compose。 docker/ 目录下提供了四个 compose 文件:

拓扑compose 文件服务
单机(推荐从这里开始)docker-compose.yml1 个 RocksDB Server + 1 个 Hubble
最小 HStore(当前主线)docker-compose-hstore.yml1 PD + 1 Store + 1 Server + 1 Hubble;需使用主线构建的本地镜像
HA 参考(当前主线)docker-compose-3pd-3store-3server.yml3 PD + 3 Store + 3 Server + 1 Hubble;需使用主线构建的本地镜像
最小 HStore 拓扑的源码构建覆盖文件docker-compose.dev.yml(需与 docker-compose-hstore.yml 一起使用)
1cd hugegraph/docker
2# 注意版本号请随时保持更新 → 1.x.0
3HUGEGRAPH_VERSION=1.7.0 docker compose -f docker-compose.yml up -d --wait

单机拓扑将 Server 暴露在 8080 端口,Hubble 暴露在 127.0.0.1:8088。HUGEGRAPH_VERSION 决定 Server、PD 和 Store 的镜像 tag,Hubble 由 HUBBLE_IMAGE 单独选择。

单机 docker-compose.yml 示例使用 HugeGraph 1.7.0 版本镜像 hugegraph/hugegraph:1.7.0;该文件引用的 docker/conf/hubble/standalone.properties 已随源码提供。Compose 文件从 HUGEGRAPH_ADMIN_PASSWORD 读取管理员密码,从 HUGEGRAPH_AUTH_TOKEN_SECRET 读取 JWT 密钥,通常放在 docker/.env 文件中。HUGEGRAPH_ADMIN_PASSWORD 非空即开启鉴权,Hubble 会自动识别该模式。若直接使用 docker run,则改为传入 -e PASSWORD=xxx。HStore Compose 文件属于当前主线,不能与 1.7.0 的 PD/Store/Server 发布镜像混用,见下文。

JWT 密钥的版本差异:当前主线构建的 Server 镜像会把 HUGEGRAPH_AUTH_TOKEN_SECRET 映射到 HG_SERVER_AUTH_TOKEN_SECRET,并写入 Server 启动配置;跨重建时应在 .env 中保留同一密钥。1.7.0 镜像的 Docker 入口脚本只处理 PASSWORD 等旧变量,不会读取 HG_SERVER_AUTH_TOKEN_SECRET。如需在 1.7.0 中固定 JWT 密钥,须将 auth.token_secret 持久写入该版本的 conf/graphs/hugegraph.properties;若保留默认随机密钥,不应假定已有 JWT 在 Server 重启后仍有效。

完整的部署指南请参阅 docker/README.md。

使用 PD 的 Server 服务标识

对于使用 PD 的 Server,Helm chart 提供 server.serviceId 和 server.graphSpace 配置项。 二者默认为 DEFAULT,此时保留 conf/rest-server.properties 中已有的 server.service_id 和 server.graphspace。 非默认值会向 Server 容器注入 HG_SERVER_SERVICE_ID 或 HG_SERVER_GRAPHSPACE。 注意:这些服务身份相关的 Chart 配置项(server.serviceId、server.graphSpace 和 server.testGraphAlias)适用于开发中的 1.8.0+ 版本镜像与 Chart; 目前尚无已发布的 Chart 或镜像支持这些选项。不要将本示例与未支持该特性的旧版本搭配使用。 通过 HG_SERVER_SERVICE_ID、SERVICE_ID 或 server.serviceId 传入的非空服务 ID 仅支持可打印 ASCII,包含空格和反斜杠; 部署校验会拒绝非 ASCII 和控制字符。此限制仅针对这些配置入口,不改变 Core Service 名称协议和已有的手工 properties 配置。 Helm 会将 server.serviceId 中的美元符号(包括 $(POD_IP))按字面量保留,不展开 Kubernetes 环境变量引用。 重读服务元数据或清理图空间时,会保留完整的服务 ID,包括其中的 / 和 -。 使用上述 chart values 设置身份;Server 的 extraEnv 会保留对应的新旧身份变量名,禁止重复覆盖。 HG_SERVER_GRAPHSPACE、生效的旧变量 GRAPH_SPACE 和 server.graphSpace 遵循同一规则: 接受 DEFAULT,或以小写字母开头、最多 48 位的小写字母、数字和下划线组成的已有空间名称:

1helm upgrade --install hg ./helm/hugegraph \
2  --set-string server.serviceId=analytics \
3  --set-string server.graphSpace=team_a

部署分配到 team_a 的 Server 前,先通过现有 DEFAULT 空间的 Server,用具有创建图空间权限的账号创建该空间。 chart 和这些环境变量不会自动创建图空间;同一个 Server Deployment 的所有副本使用相同服务标识。

用 helm test 检查该空间中的图前,先创建目标图,再将 --set-string server.testGraphAlias=team_a-demo 设置为它实际的 Gremlin 绑定。 创建图空间不会自动创建 hugegraph 图。

容器部署中的 HG_SERVER_SERVICE_ID 和 HG_SERVER_GRAPHSPACE 写入上述两个配置项。 旧名称 SERVICE_ID 和 GRAPH_SPACE 仍可使用;非空的新变量优先于对应旧变量。 同一配置项的新旧变量均未设置或为空时,保留已有值。Compose 不会自动传入宿主机上的这些变量, 需要在 Compose override 的 Server environment: 中显式添加。详见 Helm chart 配置说明。

这些设置选择 Server 在 PD 中的服务元数据,不会搬迁已有图,也不会修改未指定图空间的 REST 路径所用的 server.path_graphspace。 请求使用 /graphspaces/team_a/... 路径,并在 Hubble 中选择匹配的图空间和服务;开启鉴权时,显式指定路径仍须获得授权。

server.testGraphAlias 默认为 DEFAULT-hugegraph。hook 会逐个 Server Pod 检查这一已有本地图绑定,不会从 server.graphSpace 自动派生别名。 别名的大小写须与实际绑定一致:本地 Demo.properties 可以绑定为 DEFAULT-Demo;通过 REST 创建的图使用小写名称。 本地图绑定可以独立于 Server 在 PD 中分配的图空间存在,因此默认 hook 成功不能证明 team_a 中的图可查询。 出现 Could not rebind 时,先确认目标图存在且别名正确;重启 Pod 不能创建缺失的图或纠正别名。

配置渲染和入口脚本检查不能单独证明 Linux 上的非默认服务发现、鉴权或跨图空间隔离已通过验收。

说明
  1. HugeGraph 的 Docker 镜像主要用于便捷地快速启动 HugeGraph,并不是 ASF 官方发布物料包。你可以从 ASF Release Distribution Policy 中了解更多细节。

  2. 推荐使用 release tag (如 1.7.0/1.x.0) 以获取稳定版。使用 latest tag 可以使用开发中的最新功能。

3.2 下载已发布的 tar 包

以下示例针对 HugeGraph 1.7.0。使用其他版本时,请先在 ASF 下载目录 确认该版本及对应文件名;不要把 master 源码构建包当作已发布的二进制包。

1cd /path/to/downloads
2wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz.sha512
4sha512sum -c apache-hugegraph-incubating-1.7.0.tar.gz.sha512
5tar zxf apache-hugegraph-incubating-1.7.0.tar.gz

SHA-512 校验通过后再解压。也可按 Apache 发布流程验证 PGP 签名:

1wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz.asc
2wget https://downloads.apache.org/hugegraph/KEYS
3gpg --import KEYS
4gpg --verify apache-hugegraph-incubating-1.7.0.tar.gz.asc apache-hugegraph-incubating-1.7.0.tar.gz

只应信任通过 Apache 项目渠道核实的发布者密钥;签名验证可与 SHA-512 校验一起使用。

3.3 从 master 源码构建

下面的命令构建的是开发主线,不是 1.7.0 发布包。

源码编译前请确保本机有安装 wget/curl 命令

下载 HugeGraph 源代码

1git clone --branch master https://github.com/apache/hugegraph.git

编译打包生成 tar 包

1cd hugegraph
2# (Optional) use "-P stage" param if you build failed with the latest code(during pre-release period)
3mvn package -DskipTests -ntp

构建成功时日志中会出现:

1[INFO] BUILD SUCCESS

执行成功后,根目录 target/ 下会生成主线聚合包(当前仓库版本属性为 1.8.0):

1target/apache-hugegraph-1.8.0.tar.gz

该文件名中的版本号来自源码的 revision 属性;它不会把主线构建变成 ASF 发布物料。构建过程还会在仓库根目录生成 apache-hugegraph-1.8.0/ 聚合目录,其中的 Server 子目录名由 Server 模块的 final.name 决定,例如当前为 apache-hugegraph-server-1.8.0。若只保留了 tar 包,则先执行 tar zxf target/apache-hugegraph-1.8.0.tar.gz 再进入该目录。

默认构建会打包 rocksdb、hbase 和 hstore 三个后端模块,并把它们记录在 hugegraph-dist jar 内的 backend.properties 资源的 backends 配置项中。若只需要包含 RocksDB 的精简发布包,可加上 -Drocksdb-only:

1mvn package -DskipTests -ntp -Drocksdb-only
过时的 tools 工具安装

3.4 使用 tools 工具部署 (Outdated)

已过时 仅指此一键部署入口。

HugeGraph-Tools 提供一键部署命令,可以下载、解压、配置并启动 Server 服务和 HugeGraph-Hubble。HugeGraph-Toolchain 发布包中已包含这些工具。

1# download toolchain package, it includes loader + tool + hubble, please check the latest version (here is 1.7.0)
2wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-toolchain-incubating-1.7.0.tar.gz
3tar zxf *hugegraph-*.tar.gz
4# enter the tool's package
5cd *hugegraph*/*tool*

注:${version} 为版本号,最新版本号可参考 Download 页面,或直接从 Download 页面点击链接下载

HugeGraph-Tools 的总入口脚本是 bin/hugegraph,用户可以使用 help 子命令查看其用法,这里只介绍一键部署的命令。

1bin/hugegraph deploy -v {hugegraph-version} -p {install-path} [-u {download-path-prefix}]

{hugegraph-version} 表示要部署的 Server 服务及 HugeGraphStudio 版本,可在 conf/version-mapping.yaml 中查看版本信息。{install-path} 指定安装目录,{download-path-prefix} 可选,用于指定 tar 包下载地址。例如部署 0.6 版本时,可以执行 bin/hugegraph deploy -v 0.6 -p services。

4 配置

Server 的 tar 包随包提供 conf/rest-server.properties、conf/gremlin-server.yaml 和 conf/graphs/hugegraph.properties;源码构建包从 hugegraph-server/hugegraph-dist/src/assembly/static/conf/ 装配这些文件。解压后在 Server 安装目录内编辑配置,无需另行生成。发行包版本之间可能有默认值差异,下面涉及的默认值和启动行为按 master 主线说明。

单机 RocksDB 快速上手只需确认 conf/graphs/hugegraph.properties 使用 backend=rocksdb、serializer=binary。正常 Server 初始化会扫描 conf/graphs/ 并加载本地图配置,无需额外设置 graph.load_from_local_config=true。该选项默认 false,控制构造阶段的提前加载。图配置变化通过重启 Server 应用,不使用热重载进行维护。

详细的配置介绍请参考配置文档及配置项介绍。

5 启动

5.1 使用启动脚本启动

启动流程分为首次启动和非首次启动两种情况。首次启动前需要先初始化后端数据库,然后再启动服务。

如果服务曾被手动停止,或因其他原因需要再次启动,由于后端数据库已持久化存在,通常可以直接启动服务。

HugeGraphServer 启动时会连接后端存储并检查其版本信息。如果后端尚未初始化,或者已初始化但版本不匹配(例如存在旧版本数据),HugeGraphServer 会启动失败并给出错误信息。

如果需要外部访问 HugeGraphServer,请修改 rest-server.properties 的 restserver.url 配置项(默认为 http://127.0.0.1:8080),修改成机器名或 IP 地址。

由于各种后端所需的配置(hugegraph.properties)及启动步骤略有不同,下面逐一对各后端的配置及启动做介绍。

警告

生产环境启动 Server 前必须完成鉴权配置

按照 Server 鉴权配置 启用认证与授权并设置非默认强管理员密码;同时启用 IP 白名单,为业务用户配置最小权限。

5.1.1 分布式存储 (HStore)

要使用分布式存储引擎,需要先部署 HugeGraph-PD 和 HugeGraph-Store,详见 HugeGraph-PD 快速入门 和 HugeGraph-Store 快速入门。

警告

umask 077 保护新建的 .env,但 set-hubble-pd-password.sh 会将生成的 .local.properties 权限设为 0644,本机其他用户也能读取其中的 PD 密钥。下面示例仅适用于本机用户均可信的环境;共享主机必须先按 Hubble 运行用户设置文件属主与读取权限,确保 Hubble 可读且其他非授权用户不可读。不提交文件不能替代文件权限保护。

分布式存储配置及启动方法

分布式存储是 HugeGraph 1.5.0 之后推出的新特性,它基于 HugeGraph-PD 和 HugeGraph-Store 组件实现了分布式的数据存储和计算。

确保 PD 和 Store 服务均已启动后

  1. 修改 Server 服务的 hugegraph.properties 配置:
1backend=hstore
2serializer=binary
3
4# PD 服务地址,多个 PD 地址用逗号分割,配置 PD 的 RPC 端口
5pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
6pd.cluster=hg
 1# 简单示例(带鉴权)
 2gremlin.graph=org.apache.hugegraph.auth.HugeFactoryAuthProxy
 3
 4# 指定存储 hstore(必须)
 5backend=hstore
 6serializer=binary
 7store=hugegraph
 8
 9# pd config
10pd.peers=127.0.0.1:8686
11pd.cluster=hg

发布包中自带该后端的模板文件 conf/graphs/hstore.properties.template,可将其复制覆盖 conf/graphs/hugegraph.properties 后修改 pd.peers。

此例的 rest-server.properties 使用 cluster=hg,图配置使用 pd.cluster=hg,与下方主线 Compose 拓扑选用同一集群名。它们位于不同配置文件,分别供 Server 进程和图配置使用;按部署实际选择集群名,不要把两个键当成同一个配置项。类似地,两个文件中的 pd.peers 也属于各自的配置范围;本例都填写同一组 PD RPC 地址。

任务调度器由后端决定,无需配置 task.scheduler_type:hstore 使用分布式调度器,其余后端使用本地调度器。为兼容旧配置,该键仍可存在,但会被忽略并打印一条警告日志。

  1. 修改 Server 服务的 rest-server.properties 配置:
1usePD=true
2# 本例与图配置的 pd.cluster 共用集群名 hg
3cluster=hg
4# 配置 Server 进程连接的 PD 地址;替换为实际 PD RPC 地址
5pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
6
7# 本地测试可按需启用;生产环境必须启用鉴权
8# auth.authenticator=org.apache.hugegraph.auth.StandardAuthenticator

以下地址示例适用于在同一台主机运行多个 Server 进程;127.0.0.1 仅用于本机场景。跨主机部署时,将 restserver.url、gremlinserver.url、pd.peers、Gremlin host 和 rpc.server_host 替换为各节点可路由的 IP 或 DNS;rpc.server_host 公布的地址和端口必须能被其他节点互达。

如果配置多个 Server 节点,需要为每个节点修改 rest-server.properties 配置文件,例如:

节点 1(主节点):

 1usePD=true
 2restserver.url=http://127.0.0.1:8081
 3gremlinserver.url=http://127.0.0.1:8181
 4pd.peers=127.0.0.1:8686
 5
 6rpc.server_host=127.0.0.1
 7rpc.server_port=8091
 8
 9server.id=server-1
10server.role=master

节点 2(工作节点):

 1usePD=true
 2restserver.url=http://127.0.0.1:8082
 3gremlinserver.url=http://127.0.0.1:8182
 4pd.peers=127.0.0.1:8686
 5
 6rpc.server_host=127.0.0.1
 7rpc.server_port=8092
 8
 9server.id=server-2
10server.role=worker

同时,还需要修改每个节点的 gremlin-server.yaml 中的端口配置:

节点 1:

1host: 127.0.0.1
2port: 8181

节点 2:

1host: 127.0.0.1
2port: 8182

启动 Server:

1bin/start-hugegraph.sh

使用分布式存储引擎的启动顺序为:

  1. 启动 HugeGraph-PD
  2. 启动 HugeGraph-Store
  3. 启动 Server 服务

HStore 的元数据和存储由 PD、Store 管理,init-store 会跳过该后端。开启鉴权时,执行 init-store 仍会创建内置的 admin 账号。如果该账号已由存储侧持有,可在 rest-server.properties 中设置 init_store.enabled=false 以整体跳过这一步,Docker 的 HStore 拓扑即采用这种方式。

验证服务是否正常启动:

1curl http://localhost:8081/graphspaces/DEFAULT/graphs
2# 应返回:{"graphs":["hugegraph"]}

停止服务的顺序应该与启动顺序相反:

  1. 停止 Server 服务
  2. 停止 HugeGraph-Store
  3. 停止 HugeGraph-PD
1bin/stop-hugegraph.sh
Docker HStore 高可用集群(当前主线)

docker-compose-3pd-3store-3server.yml 使用当前主线的 HG_PD_*、HG_STORE_* 和 HG_SERVER_* 环境变量;1.7.0 发布镜像不支持这套配置。先从同一份主线源码构建 PD、Store 和 Server 镜像,并使用相同的本地 local 标签:

1# 在 hugegraph 仓库根目录执行
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .
3docker build -f hugegraph-store/Dockerfile -t hugegraph/store:local .
4docker build -f hugegraph-server/Dockerfile-hstore -t hugegraph/server:local .
5
6cd docker

先在 docker/ 目录创建认证环境并生成 HStore Hubble 配置。用自己设置的管理员密码替换示例文本;因 .env 使用单引号包裹,密码不能含单引号或换行。脚本生成 JWT 与 PD 随机密钥,并将 PD 密钥写入两个 HStore Compose 会挂载的未跟踪 .local.properties 文件:

 1(
 2  set -eu
 3  command -v openssl >/dev/null
 4  jwt_secret="$(openssl rand -hex 32)"
 5  pd_secret="$(openssl rand -hex 24)"
 6  umask 077
 7  test ! -e .env || {
 8    echo ".env already exists; edit it instead of overwriting it" >&2
 9    exit 1
10  }
11  printf "HUGEGRAPH_ADMIN_PASSWORD='%s'\nHUGEGRAPH_AUTH_TOKEN_SECRET='%s'\nHG_PD_AUTH_SECRET_KEY='%s'\n" \
12    'replace-with-your-password' "${jwt_secret}" "${pd_secret}" > .env
13  HG_PD_AUTH_SECRET_KEY="${pd_secret}" ./set-hubble-pd-password.sh hstore
14  HG_PD_AUTH_SECRET_KEY="${pd_secret}" ./set-hubble-pd-password.sh hstore-ha
15)

然后在 docker/ 目录启动 HA 拓扑。HUGEGRAPH_VERSION=local 令 PD、Store 和 Server 使用刚构建的本地镜像;该 Compose 文件的 pull_policy: missing 会优先使用已存在的本地标签。Hubble 仍由 HUBBLE_IMAGE 独立选择:

1set -a
2. ./.env
3set +a
4HUGEGRAPH_VERSION=local docker compose \
5  -f docker-compose-3pd-3store-3server.yml \
6  up -d --wait pd0 pd1 pd2 store0 store1 store2 server0 server1 server2 hubble

HG_PD_AUTH_SECRET_KEY 应只为新数据目录生成一次;重启或复用已有数据目录时,继续使用原值。不要提交 .env 或生成的 conf/hubble/*.local.properties。服务通过 hg-net 桥接网络上的容器主机名通信。Server 拓扑要求共享 JWT 密钥;不要只设置管理员密码而遗漏 HUGEGRAPH_AUTH_TOKEN_SECRET。完整的环境变量说明见 Docker 集群指南 和仓库 docker/README.md。

验证集群:

1curl -fsS http://localhost:8080/versions
2curl -fsS -u "hg:${HG_PD_AUTH_SECRET_KEY:?请先加载 .env}" \
3  http://localhost:8620/v1/stores

当前主线的 PD /v1/stores REST 接口需要 HTTP Basic 认证;此处用生成后已加载的 HG_PD_AUTH_SECRET_KEY 作为 hg 用户密码。

运行时日志可通过 docker logs <container-name>(如 docker logs hg-pd0)直接查看,无需进入容器。

完整的环境变量参考、端口表和故障排查指南请参阅 docker/README.md。

5.1.2 RocksDB / ToplingDB

从 master 构建的单机最小流程如下。此例启用内置样例数据,以便后续请求能验证图数据读写路径。

  1. 检查 Java 环境,确认满足主线构建要求。
  2. 构建 master 源码;下方命令使用该构建包中的 Server 子目录。
  3. 确认 RocksDB 配置,再进入构建产物中的 Server 子目录。
  4. 初始化存储,然后启动服务并加载样例图,命令见下方。
  5. 请求 /versions 和样例图顶点接口,检查实际返回内容。
说明

RocksDB 是一个嵌入式的数据库,不需要手动安装部署,要求 GCC 版本 >= 4.3.0(GLIBCXX_3.4.10),如不满足,需要提前升级 GCC

主线包内的 conf/graphs/hugegraph.properties 默认已设置 backend=rocksdb 和 serializer=binary。使用默认数据目录时无需修改;若改过后端或数据路径,先确认配置,再初始化存储。

初始化数据库(首次启动,或在 conf/graphs/ 下添加了新图配置后):

1cd apache-hugegraph-1.7.0/apache-hugegraph-server-1.7.0
2bin/init-store.sh

启动 Server 并加载内置样例图:

1bin/start-hugegraph.sh -p true

启动脚本会按 rest-server.properties 中的 restserver.url 轮询 /graphs,超时或进程失败时以非零状态退出。随后先检查服务版本,再读取样例顶点:

1curl -fsS http://127.0.0.1:8080/versions
2curl --compressed -fsS \
3  http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices

第一条请求应返回包含 versions 的 JSON;第二条应返回包含 vertices 的 JSON,且样例数据中可见 marko、lop 等顶点。仅检查进程存在或 HTTP 状态码,不足以证明图后端和业务请求正常。

ToplingDB (Beta): 作为 RocksDB 的高性能替代方案,配置方式请参考: ToplingDB 快速上手

5.1.3 HBase

说明

用户需自行安装 HBase,要求版本 2.0 以上,下载地址

HBase 配置及启动方法

修改 hugegraph.properties

 1backend=hbase
 2serializer=hbase
 3
 4# hbase backend config
 5hbase.hosts=localhost
 6hbase.port=2181
 7# Note: recommend to modify the HBase partition number by the actual/env data amount & RS amount before init store
 8# it may influence the loading speed a lot
 9#hbase.enable_partition=true
10#hbase.vertex_partitions=10
11#hbase.edge_partitions=30

初始化数据库(第一次启动时或在 conf/graphs/ 下手动添加了新配置时需要进行初始化)

1cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-server-incubating-1.7.0
2bin/init-store.sh

启动 server

1bin/start-hugegraph.sh
2Starting HugeGraphServer in daemon mode...
3Connecting to HugeGraphServer (http://127.0.0.1:8080/graphs)....OK
4Started [pid 21614]

更多其它后端配置可参考配置项介绍

5.1.4 启动 server 的时候创建示例图

在启动脚本时携带 -p true 参数,表示开启 preload,即创建示例图。

1bin/start-hugegraph.sh -p true
2Starting HugeGraphServer in daemon mode...
3Connecting to HugeGraphServer (http://127.0.0.1:8080/graphs)......OK

并且使用 RESTful API 请求 HugeGraphServer 得到如下结果:

1> curl "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices" | gunzip
2
3{"vertices":[{"id":"2:lop","label":"software","type":"vertex","properties":{"name":"lop","lang":"java","price":328}},{"id":"1:josh","label":"person","type":"vertex","properties":{"name":"josh","age":32,"city":"Beijing"}},{"id":"1:marko","label":"person","type":"vertex","properties":{"name":"marko","age":29,"city":"Beijing"}},{"id":"1:peter","label":"person","type":"vertex","properties":{"name":"peter","age":35,"city":"Shanghai"}},{"id":"1:vadas","label":"person","type":"vertex","properties":{"name":"vadas","age":27,"city":"Hongkong"}},{"id":"2:ripple","label":"software","type":"vertex","properties":{"name":"ripple","lang":"java","price":199}}]}

代表创建示例图成功。

5.1.5 启动脚本的参数

bin/start-hugegraph.sh 支持以下参数。每个参数都需要带值,即写作 -d false,不能只写 -d。

参数取值默认值作用
-dtrue、falsetrue守护进程模式。-d false 时脚本留在前台,并把 SIGTERM/SIGINT 转发给服务进程
-gg1、G1、zgc、ZGCJVM 默认值选择垃圾回收器(g1/G1 设置 -XX:+UseG1GC;zgc/ZGC 设置 -XX:+UseZGC)。不填则使用 JVM 默认收集器配置
-mtrue、falsefalse安装基于 crontab 的监控任务(bin/start-monitor.sh),仅用于虚拟机和物理机部署
-ptrue、falsefalse预加载示例图,见 5.1.4
-strue、falsetrue开启安全检查(HugeSecurityManager),要求 Java 17 到 23 以及 conf/java-security.properties 可读。在 Java 24+ 上需传 -s false
-jJVM 参数空追加到服务命令行的额外 JVM 参数
-t秒30判定启动失败前等待服务响应的时长
-ytrue、falsefalse开启 OpenTelemetry agent 上报链路追踪

bin/stop-hugegraph.sh 支持 -m true|false(默认 true),用于控制停止服务时是否同时移除 crontab 监控任务。

bin/hugegraph-server.sh 会把 -XX:+HeapDumpOnOutOfMemoryError、-XX:HeapDumpPath 和 -XX:ErrorFile 放在 JAVA_TOOL_OPTIONS 的最前面。因此无论是否设置了 JAVA_OPTIONS(下文所述的例外情况除外),内存溢出时的堆转储(heapdump_<主机名>_<启动时间>/java_pid<pid>.hprof)和 JVM 崩溃日志(hs_err_pid<pid>_<主机名>_<启动时间>.log)都会写入 logs/,其中 <启动时间> 为本地时间,格式是 YYYYMMDD-HHMMSS。每次启动都有自己的 heapdump_* 目录,因此服务及其启动的 JVM(例如 computer 任务)会分别写入各自的转储(HotSpot 按 JVM 的 PID 命名转储文件和崩溃日志,因此同一次启动中复用了先前 PID 的 JVM 无法写入它的转储,它的崩溃日志也会覆盖先前那个 JVM 的)。主机名可避免共用同一日志目录的多个服务选到相同的名字;如果同一主机在同一秒内已经用过该名字,会再加上计数(<启动时间>-1、-2……)。如果无法创建该目录(例如磁盘已满),服务仍会启动,堆转储改为尽力写入 logs/ 本身;磁盘已满时可能也没有空间写入转储。堆转储可能和堆一样大。启动脚本从不删除转储或 heapdump_* 目录:每次启动到 Java 阶段都会留下一个目录,除非发生内存溢出否则为空;启动脚本保留它,是因为 computer 任务的 JVM 可能在服务退出后仍在使用它。在该次启动的 HugeGraph JVM 都已退出后,可以移走或删除旧目录,但不要动正在运行的服务最新的那个目录;没有它,下一次转储会被写成一个同名文件。JVM 会在这些默认值之后读取你自己的 JAVA_TOOL_OPTIONS、JDK_JAVA_OPTIONS(包括 @argfile)、命令行(JAVA_OPTIONS;未设置或为空时为 -j)和 _JAVA_OPTIONS,因此在其中任意一处为上述参数指定的值都会覆盖默认值。只有环境变量会传给服务启动的 JVM:要对所有 JVM 关闭堆转储,请设置 JAVA_TOOL_OPTIONS=-XX:-HeapDumpOnOutOfMemoryError;通过 -j 或 JAVA_OPTIONS 关闭只对服务自身的 JVM 生效。无论哪种方式,每次启动到 Java 阶段仍会创建空的 heapdump_* 目录,除非创建失败而改为写入 logs/。如果日志路径中包含双引号或 %,启动脚本会给出警告,堆转储直接写入 logs/,不使用每次启动的目录,也不设置崩溃日志的默认值;通过 JAVA_TOOL_OPTIONS 关闭堆转储的方式仍然有效。同时包含两种引号的路径则完全不设置堆转储默认值。由于设置了这些默认值,JVM 启动时会在 stderr 输出 Picked up JAVA_TOOL_OPTIONS: ...。

版本范围:以上行为适用于当前开发分支/master 分支。1.7.0 只在未设置 JAVA_OPTIONS 时添加堆转储参数,堆转储直接写入 logs/java_pid<pid>.hprof,JVM 崩溃日志写入安装目录。

5.2 使用 Docker

在 3.1 使用 Docker 容器 中,我们已经介绍了如何使用 docker 部署 Server 服务。还可以通过切换后端存储或设置参数,在 Server 启动时加载样例图。

5.2.1 启动 server 的时候创建示例图

在 Docker 启动时设置环境变量 PRELOAD=true,即可在启动脚本执行过程中加载样例数据。

  1. 使用docker run

    使用 docker run -itd --name=server -p 8080:8080 -e PRELOAD=true hugegraph/hugegraph:1.7.0

  2. 使用docker-compose

    创建docker-compose.yml,具体文件如下,在环境变量中设置 PRELOAD=true。其中,example.groovy 是一个预定义的脚本,用于预加载样例数据。如果有需要,可以通过挂载新的 example.groovy 脚本改变预加载的数据。

     1version: '3'
     2services:
     3  server:
     4    image: hugegraph/hugegraph:1.7.0
     5    container_name: server
     6    environment:
     7      - PRELOAD=true
     8      - PASSWORD=xxx
     9    volumes:
    10      - /path/to/yourscript:/hugegraph-server/scripts/example.groovy
    11    ports:
    12      - 8080:8080

    基于当前 master 构建的 Server 镜像以非 root 的 UID 10001 运行,挂载的脚本必须对该用户可读。

    使用命令 docker compose up -d 启动容器

使用 RESTful API 请求 HugeGraphServer 得到如下结果:

1> curl "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices" | gunzip
2
3{"vertices":[{"id":"2:lop","label":"software","type":"vertex","properties":{"name":"lop","lang":"java","price":328}},{"id":"1:josh","label":"person","type":"vertex","properties":{"name":"josh","age":32,"city":"Beijing"}},{"id":"1:marko","label":"person","type":"vertex","properties":{"name":"marko","age":29,"city":"Beijing"}},{"id":"1:peter","label":"person","type":"vertex","properties":{"name":"peter","age":35,"city":"Shanghai"}},{"id":"1:vadas","label":"person","type":"vertex","properties":{"name":"vadas","age":27,"city":"Hongkong"}},{"id":"2:ripple","label":"software","type":"vertex","properties":{"name":"ripple","lang":"java","price":199}}]}

代表创建示例图成功。

6 访问 Server

6.1 服务启动状态校验

jps 查看服务进程

1jps
26475 HugeGraphServer

curl 请求 RESTful API

1curl -fsS http://127.0.0.1:8080/versions

返回包含 versions 的 JSON(HTTP 2xx)可确认 REST API 已响应。jps 中出现 HugeGraphServer 只表示进程存在;要确认图后端可用,请按单机流程加载样例图后请求顶点接口。

6.2 请求 Server

HugeGraphServer 的 RESTful API 包括多种类型的资源,典型的包括 graph、schema、gremlin、traverser 和 task

  • graph 包含 vertices、edges
  • schema 包含 vertexlabels、propertykeys、edgelabels、indexlabels
  • gremlin 包含各种 Gremlin 语句,如 g.v(),可以同步或者异步执行
  • traverser 包含各种高级查询,包括最短路径、交叉点、N 步可达邻居等
  • task 包含异步任务的查询和删除

6.2.1 获取 hugegraph 的顶点及相关属性

1curl http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices

说明

  1. 对于顶点、边等列表请求,Server 可以压缩响应。使用 curl --compressed 可自动解压:

    1curl --compressed -fsS "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices"
  2. 默认监听地址为 127.0.0.1,其他机器无法直接访问。

警告

调整 Server 监听地址

若将地址调整为 0.0.0.0,Server 将监听所有网卡。生产环境必须启用认证与授权、IP 白名单及最小权限授权,并保留和保护审计日志;不得将 Gremlin、Cypher 等接口直接暴露到公网。

1vim conf/rest-server.properties
2
3restserver.url=http://0.0.0.0:8080

响应体如下:

 1{
 2    "vertices": [
 3        {
 4            "id": "2lop",
 5            "label": "software",
 6            "type": "vertex",
 7            "properties": {
 8                "price": [
 9                    {
10                        "id": "price",
11                        "value": 328
12                    }
13                ],
14                "name": [
15                    {
16                        "id": "name",
17                        "value": "lop"
18                    }
19                ],
20                "lang": [
21                    {
22                        "id": "lang",
23                        "value": "java"
24                    }
25                ]
26            }
27        },
28        {
29            "id": "1josh",
30            "label": "person",
31            "type": "vertex",
32            "properties": {
33                "name": [
34                    {
35                        "id": "name",
36                        "value": "josh"
37                    }
38                ],
39                "age": [
40                    {
41                        "id": "age",
42                        "value": 32
43                    }
44                ]
45            }
46        },
47        ...
48    ]
49}

详细的 API 请参考 RESTful-API 文档。

另外也可以通过访问 localhost:8080/swagger-ui/index.html 查看 API。

Swagger UI 中的 HugeGraph RESTful API 接口列表

在使用 Swagger UI 调试 HugeGraph 提供的 API 时,如果 HugeGraph Server 开启了鉴权模式,可以在 Swagger 页面输入鉴权信息。

HugeGraph Swagger UI 中的 Authorize 按钮

当前 HugeGraph 支持基于 Basic 和 Bearer 两种形式设置鉴权信息。

Swagger UI 授权对话框中的 Basic 和 Bearer 凭据输入框

7 停止 Server

1cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-server-incubating-1.7.0
2bin/stop-hugegraph.sh

8 使用 IntelliJ IDEA 调试 Server

请参考在 IDEA 中配置 Server 开发环境

1.2 - HugeGraph-PD 快速上手

1 HugeGraph-PD 概述

HugeGraph-PD(Placement Driver)是 HugeGraph 分布式版本的元数据管理组件,负责管理图数据的分布和存储节点的协调。它在分布式 HugeGraph 中扮演着核心角色,维护集群状态并协调 HugeGraph-Store 存储节点。

PD 将集群元数据保存在 pd.data-path 下的内嵌 RocksDB 中,并通过 Raft 在各 PD 节点之间复制,因此 3 节点或 5 节点的 PD 集群在少数节点宕机时仍可继续提供服务。在此基础上,PD 还负责注册和激活 Store 节点、分配与再平衡分区、跟踪 Store 心跳,并响应来自 Store 和 Server 的服务发现请求。

PD 监听三个端口:

端口默认值配置项使用方
gRPC8686grpc.portStore 和 Server 客户端
REST8620server.port管理接口、健康检查、监控指标
Raft8610raft.address仅其他 PD 节点

2 依赖

2.1 前置条件

  • 操作系统:Linux 或 macOS(Windows 尚未经过完整测试)
  • Java 版本:HugeGraph 1.8.0+ 使用 Java 17(Maven 源码构建仅接受 JDK 17;启动脚本拒绝低于 17 的运行时;1.7.0 是最后一个支持 Java 11 的版本)
  • Maven 版本:≥ 3.6.3(从源码编译时)

3 部署

有两种方式可以部署 HugeGraph-PD 组件:

  • 方式 1:下载 tar 包
  • 方式 2:源码编译

3.1 下载 tar 包

Apache 下载页目前提供 1.7.0 的完整二进制包,其中包含 PD、Store 和 Server;没有单独列出 PD 二进制包。下载前请在 官方 Apache HugeGraph 下载页核对版本、签名和 SHA512。1.7.0 是孵化期发布的历史版本,归档文件和解压目录仍带 incubating:

1# 1.7.0 是项目孵化期发布的历史版本,因此文件名和目录名仍带 incubating
2curl -fLO --connect-timeout 10 --max-time 1800 https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3tar zxf apache-hugegraph-incubating-1.7.0.tar.gz
4cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-pd-incubating-1.7.0

3.2 源码编译

 1# 1. 克隆源代码
 2git clone https://github.com/apache/hugegraph.git
 3
 4# 2. 编译项目
 5cd hugegraph
 6mvn clean install -DskipTests=true
 7
 8# 3. 编译成功后,PD 目录和发布包分别位于
 9#    hugegraph-pd/apache-hugegraph-pd-{version}          (解压后的 PD 发布目录)
10#    hugegraph-pd/apache-hugegraph-pd-{version}.tar.gz   (仅含 PD 的发布包,只在 Linux 构建机上生成)
11#    target/apache-hugegraph-{version}.tar.gz            (PD + Store + Server 的完整发布包)

只编译 PD 发布包及其依赖模块:

1mvn clean package -pl hugegraph-pd/hg-pd-dist -am -DskipTests

解压后的发布目录只包含三个子目录:bin(启停脚本)、conf(application.yml、application.yml.template、log4j2.xml、verify-license.json)和 lib(hg-pd-service jar 包)。

3.3 Docker 部署

HG_PD_* 环境变量和 /v1/ready 是当前主线源码提供的功能;server 的 1.7.0 发布源码标签尚无这些 Docker 环境变量映射或 readiness API。本文下面的 Docker 示例仅适用于从当前主线源码构建并标记为 local 的镜像;使用 1.7.0 发布资产时,应以该版本随包配置和说明为准:

1# 在 hugegraph 仓库根目录执行
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .

单独运行当前主线构建的 PD 时,先设置部署专用密钥,并把示例地址替换为容器可达的真实地址:

下面的 mkdir -p 和非递归 chown 仅适用于新建空目录。复用旧 root 镜像写入的数据时,先停止 PD, 执行一次 sudo chown -R 10001:10001 /path/to/data,再启动 UID 10001 镜像。

 1export HG_PD_AUTH_SECRET_KEY="$(openssl rand -hex 24)"
 2# master 构建的镜像以 UID 10001 运行,宿主机数据目录必须对该用户可写
 3mkdir -p /path/to/data && sudo chown 10001:10001 /path/to/data
 4docker run -d \
 5  -p 8620:8620 -p 8686:8686 -p 8610:8610 \
 6  -e HG_PD_GRPC_HOST=192.168.1.10 \
 7  -e HG_PD_RAFT_ADDRESS=192.168.1.10:8610 \
 8  -e HG_PD_RAFT_PEERS_LIST=192.168.1.10:8610 \
 9  -e HG_PD_INITIAL_STORE_LIST=192.168.1.20:8500 \
10  -e HG_PD_AUTH_SECRET_KEY="$HG_PD_AUTH_SECRET_KEY" \
11  -v /path/to/data:/hugegraph-pd/pd_data \
12  --name hugegraph-pd \
13  hugegraph/pd:local
变量必填默认值对应配置项描述
HG_PD_GRPC_HOST是无grpc.host本节点对外公布的 gRPC 主机名/IP;容器网络中应使用容器主机名。
HG_PD_RAFT_ADDRESS是无raft.address本节点 Raft 地址。
HG_PD_RAFT_PEERS_LIST是无raft.peers-list所有 PD 节点的 Raft 地址,含本节点。
HG_PD_INITIAL_STORE_LIST是无pd.initial-store-list预期的 Store gRPC 地址。
HG_PD_AUTH_SECRET_KEY是无auth.secret-keyREST Basic 密码;所有 PD REST 客户端都必须使用同一密钥。
HG_PD_GRPC_PORT否8686grpc.portgRPC 服务端口。
HG_PD_REST_PORT否8620server.portREST API 端口。
HG_PD_DATA_PATH否/hugegraph-pd/pd_datapd.data-path元数据存储路径。
HG_PD_INITIAL_STORE_COUNT否1pd.initial-store-count集群可用所需的最小 Store 数量。
HG_PD_ACTUATOR_EXPOSURE否health,metrics,prometheusmanagement.endpoints.web.exposure.include公开的 Actuator 端点白名单;不允许设置为 *。

当前主线 entrypoint 要求以上五个必填变量,生成 SPRING_APPLICATION_JSON 覆盖项后再启动 PD;其他配置继续从镜像内的 conf/application.yml 读取。JAVA_OPTS 会透传给 JVM。旧变量 GRPC_HOST、RAFT_ADDRESS、RAFT_PEERS、PD_INITIAL_STORE_LIST 仍可用,但会输出弃用警告。

PD 镜像的 Docker HEALTHCHECK 每 15 秒检查 /v1/health,它只表示 REST 监听器有响应,不代表 Raft 已形成多数派。Compose 示例中的健康检查也使用这个存活接口;需要在启动 Store 前另行检查 /v1/ready。容器以前台方式运行,Java 退出会让容器退出;只有配置了 Docker 重启策略时容器才会自动重启。Docker 日志可通过 docker logs <container-name> 查看。

当前主线 Compose 的完整启动和最小拓扑见 Store 页面及 docker/README.md。Compose 文件的服务配置来自主线源码;若启动包含 Hubble 的完整拓扑,先按 docker/README.md 生成未跟踪的 Hubble 配置文件。

4 配置

PD 启动脚本读取安装目录中的 conf/application.yml。请使用与安装包版本相同的源文件,不要把发布版和主线配置混用: 1.7.0 发布标签配置;当前主线配置。主线 application.yml 将 auth.secret-key 留空,REST 受保护接口在未设置密钥时会拒绝请求;application.yml.template 不由 PD 启动脚本读取。

4.1 配置项参考

以下表格列出主线配置及代码默认值,Raft 超时设置可参阅 PDConfig 实现。1.7.0 二进制包请使用对应标签的原始配置;主线源码构建包则以 主线配置文件 为准。下文会单独说明与 1.7.0 的差异。

gRPC 与 REST

配置项主线目录值内置默认值描述
grpc.host127.0.0.1无,必填本 PD 对外公布的 gRPC 地址。Store 和 Server 会连到这个地址,因此分布式部署时必须填可访问的 IPv4 地址或主机名,不能用 127.0.0.1 或 0.0.0.0。
grpc.port8686无,必填gRPC 端口。
server.port8620无,必填REST API 端口,同时也是 Raft 成员信息中公布的 REST 端口。

application.yml.template 中还有 grpc.netty-server.max-inbound-message-size: 100MB,但 PD 在代码中把 gRPC 服务端的入站消息上限固定为 1 GB,该配置项实际不生效。

Raft

配置项主线目录值内置默认值描述
raft.address127.0.0.1:8610无,必填本节点的 Raft 地址,格式为 host:port。每个节点必须不同,且必须出现在 raft.peers-list 中。
raft.peers-list127.0.0.1:8610无,必填逗号分隔的全部 PD 节点 Raft 地址(含本节点)。所有节点上必须完全一致。
raft.enable未设置true为 true 时元数据写入经过 Raft 状态机;为 false 时 PD 直接写本地存储,不做复制。
raft.ip-whitelist.enabled未设置true为 true 时 Raft RPC 端口只接受由 raft.peers-list 解析出的地址的连接,其他连接会被断开并记录 Blocked connection from <ip>。peer 列表变更时白名单会重新解析,但主机名不变而 IP 变化的情况(例如容器重启)仍需重启 PD。
raft.snapshotInterval未设置300Raft 快照生成间隔(秒)。
raft.rpc-timeout未设置10000PD 节点之间 Raft RPC 的超时时间(毫秒)。PD 读取 id 计数器前等待 ReadIndex 的时限也是这个值,超过时限则 id 分配失败。
raft.rpc-connect-timeout未设置1000与 peer 建立 Raft 连接时 Ping 的超时时间(毫秒)。候选节点逐个连接 peer,某个 peer 接受了 TCP 连接却不应答时,选举会为它等待这么久。已建立连接上的请求使用 raft.rpc-timeout。
raft.rpc-install-snapshot-timeout未设置0向落后于日志的 follower 发送快照的超时时间(毫秒)。0 表示使用 raft.rpc-timeout。快照较大而超时时可调大。

raft.rpc-connect-timeout 和 raft.rpc-install-snapshot-timeout 仅在 1.7.0 之后的版本中提供。1.7.0 中 raft.rpc-timeout 同时也是连接超时和安装快照超时,id 分配也不等待 ReadIndex。

PD 核心

配置项主线目录值内置默认值描述
pd.data-path./pd_data无,必填元数据目录。rocksdb/ 子目录存放 RocksDB 数据,pd_raft/ 子目录存放 Raft 日志、元信息和快照。
pd.patrol-interval1800300巡检周期(秒)。巡检会检查各 Store 上的分区健康状况并平衡分区数量。
pd.initial-store-count13活跃 Store 节点的最小数量。低于该值时集群状态变为 Cluster_Not_Ready,整个集群视为不可用。建议设为实际部署的 Store 数量。
pd.initial-store-list127.0.0.1:8500空逗号分隔的 Store gRPC 地址(ip:port),列表中的 Store 注册后自动激活。条目也可以带分组 id,写作 store_address/group_id。
pd.cluster_id未设置1集群 id,用于区分不同的 PD 集群。

Store 管理

配置项主线目录值内置默认值描述
store.keepAlive-timeout未设置300心跳超时时间(秒)。超过该时间未收到心跳,Store 视为临时不可用,其分区 leader 转移到其他副本。
store.max-down-time1728001800超过该时间(秒)后 Store 视为永久不可用,其副本重新分配到其他机器。
store.monitor_data_enabledtruefalse是否持久化 Store 监控采样数据。
store.monitor_data_interval1 minute1 minute采样间隔,格式为 <数字> <单位>,单位为 second、minute、hour、day、month、year 之一;省略数字时按 1 计。
store.monitor_data_retention1 day1 day监控数据保留时长,格式同上。

分区

配置项主线目录值内置默认值描述
partition.default-shard-count13每个分区的副本数。生产集群建议设为 3。
partition.store-max-shard-count1224单个 Store 最多承载的分区副本数。

初始分区数由这两个配置项和 pd.initial-store-list 的长度推导得出:

1初始分区数 = Store 数量 * partition.store-max-shard-count / partition.default-shard-count

服务发现、License 与监控

配置项主线目录值内置默认值描述
discovery.heartbeat-try-count未设置3客户端注册后连续丢失多少次心跳就删除其注册信息。
license.verify-path./conf/verify-license.json无,配置键必填PD 发行目录随包提供该 JSON 文件;当前主线代码没有读取此配置项的运行时位置。
license.license-path./conf/hugegraph.license无,配置键必填目标路径不会随包带入 license 文件;内部 gRPC putLicense 会把上传内容写到此处。当前主线的 REST GET /v1/license 返回空对象,不因文件缺失而阻止 PD 启动。
auth.secret-key空空当前主线的 PD REST Basic 密码;合法用户名为 hg、store、hubble、vermeer。Docker 镜像要求设置;裸机 PD 可在密钥为空时启动,但受保护 REST 请求都会被拒绝。
management.metrics.export.prometheus.enabledtrueSpring Boot 默认值是否暴露 /actuator/prometheus。
management.endpoints.web.exposure.includehealth,metrics,prometheusSpring Boot 默认只暴露 healthActuator 暴露白名单;这些端点不经过 PD REST Basic 拦截器。
logging.configfile:./conf/log4j2.xml无Log4j2 配置文件,会写出 logs/hugegraph-pd.log、logs/hugegraph-pd_raft.log 和 logs/audit-hugegraph-pd.log。

线程池

配置项内置默认值描述
thread.pool.grpc.core600处理 gRPC 请求的线程池核心线程数。
thread.pool.grpc.max1000该线程池的最大线程数。
thread.pool.grpc.queue无上限该线程池的队列容量。
job.uninterruptibleThreadPool.core0元数据后台任务线程池的核心线程数。小于等于 0 时取可用处理器数的一半。
job.uninterruptibleThreadPool.max256该线程池的最大线程数。
job.uninterruptibleThreadPool.queue无上限该线程池的队列容量。

4.2 单节点配置

在主线源码构建的发布目录中,以 conf/application.yml 为基础,只需按节点改写 gRPC/Raft 地址和数据路径,并设置 auth.secret-key。以下值仅适用于开发测试;单节点 PD 不提供多数派容错,partition.default-shard-count: 1 表示每个分区只有一个副本。

 1grpc:
 2  host: 127.0.0.1
 3  port: 8686
 4server:
 5  port: 8620
 6raft:
 7  address: 127.0.0.1:8610
 8  peers-list: 127.0.0.1:8610
 9pd:
10  data-path: ./pd_data
11  initial-store-count: 1
12  initial-store-list: 127.0.0.1:8500
13partition:
14  default-shard-count: 1
15auth:
16  secret-key: 替换为部署专用密钥

可以用 openssl rand -hex 24 生成部署密钥;使用 Docker 时通过 HG_PD_AUTH_SECRET_KEY 传入。1.7.0 发布标签的认证行为不同,详见“REST API 认证”。

4.3 三节点集群配置

生产环境请部署 3 个或 5 个 PD 节点,节点数取奇数以保证 Raft 总能形成多数派。3 节点集群可容忍 1 个节点故障。raft.peers-list 必须列出全部节点,并且在所有节点上逐字节一致;grpc.host 和 raft.address 每个节点各不相同。

节点 1(192.168.1.10):

 1grpc:
 2  host: 192.168.1.10
 3  port: 8686
 4server:
 5  port: 8620
 6raft:
 7  address: 192.168.1.10:8610
 8  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610
 9pd:
10  data-path: /data/pd
11  initial-store-count: 3
12  initial-store-list: 192.168.1.20:8500,192.168.1.21:8500,192.168.1.22:8500
13partition:
14  default-shard-count: 3

节点 2(192.168.1.11)和节点 3(192.168.1.12)使用同一份配置,只把 grpc.host 和 raft.address 换成自己的地址:

 1# 节点 2
 2grpc:
 3  host: 192.168.1.11
 4raft:
 5  address: 192.168.1.11:8610
 6  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610
 7
 8# 节点 3
 9grpc:
10  host: 192.168.1.12
11raft:
12  address: 192.168.1.12:8610
13  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610

若要在同一台机器上启动 3 个 PD 节点做测试,需为每个节点分别指定 pd.data-path 和各自的端口,例如 raft 端口 8610/8611/8612、gRPC 端口 8686/8687/8688、REST 端口 8620/8621/8622。

在 Docker 桥接网络中,同样的配置来自环境变量,并使用容器主机名而非 IP 地址:

 1# 所有 PD 节点共用同一个密钥,实际部署从私密环境变量注入
 2HG_PD_AUTH_SECRET_KEY: ${HG_PD_AUTH_SECRET_KEY:?set HG_PD_AUTH_SECRET_KEY}
 3
 4# pd0
 5HG_PD_GRPC_HOST: pd0
 6HG_PD_RAFT_ADDRESS: pd0:8610
 7HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610
 8HG_PD_INITIAL_STORE_LIST: store0:8500,store1:8500,store2:8500
 9HG_PD_INITIAL_STORE_COUNT: 3
10
11# pd1
12HG_PD_GRPC_HOST: pd1
13HG_PD_RAFT_ADDRESS: pd1:8610
14HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610
15
16# pd2
17HG_PD_GRPC_HOST: pd2
18HG_PD_RAFT_ADDRESS: pd2:8610
19HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610

5 启动与停止

5.1 启动 PD

在 PD 安装目录下执行:

1./bin/start-hugegraph-pd.sh

脚本要求 PATH 或 JAVA_HOME 中有 17 及以上版本的 JDK(1.7.0 要求 11 及以上);如果发现已有 Java 进程在使用本安装目录的 conf 目录,脚本会直接退出,不做任何事。

下文的生命周期说明适用于当前主线构建;上文下载的 1.7.0 启动脚本不包含这些修复。 支持的参数如下,GC 的版本限制见下文:

参数取值默认值描述
-dtrue、falsetrue守护进程模式,详见下文。
-g见下文版本限制不设置选择垃圾回收器;不支持的参数会中止启动。
-jJVM 参数空额外的 JVM 参数,例如 -j "-Xmx8g -Xms8g"。
-ytrue、falsefalse挂载 OpenTelemetry Java agent。首次使用时会把 agent 下载到 plugins/ 并校验 MD5,trace 通过 gRPC 上报到 http://127.0.0.1:4317。

master 构建接受 g1、G1、zgc 和 ZGC。 上文下载的 1.7.0 启动脚本仅接受显式指定 zgc 或 ZGC;-g g1、-g G1 和其他参数会中止启动。 默认路径请省略 -g;参数被拒绝时,查看 logs/hugegraph-pd-stdout.log。

-d 参数控制守护进程模式:

  • -d true(默认):以后台守护进程方式运行,脚本立即返回。
  • -d false:以前台模式运行,脚本通过 exec 替换为 Java 进程,容器/进程管理器的进程即为 Java 本身。在 Docker 或进程管理器(systemd、supervisord)下运行时请使用此参数,以便在崩溃时自动检测并重启服务。

每个参数都有对应的环境变量:DAEMON、GC_OPTION、USER_OPTION 和 OPEN_TELEMETRY。设置 JAVA_OPTIONS 会完全替换脚本计算出的堆参数,否则脚本会根据可用内存在 512 MB 到 32 GB 之间选择堆大小。设置 STDOUT_MODE=true 时 JVM 输出保留在 stdout,不再重定向到 logs/hugegraph-pd-stdout.log,Docker 镜像正是这样做的。

启动成功后,可以在 logs/hugegraph-pd-stdout.log 中看到类似以下的日志:

1YYYY-mm-dd xx:xx:xx [main] [INFO] o.a.h.p.b.HugePDServer - Started HugePDServer in x.xxx seconds (JVM running for x.xxx)

进程号会写入 bin/pid。

5.2 停止 PD

在 PD 安装目录下执行:

1./bin/stop-hugegraph-pd.sh

脚本读取 bin/pid,向该进程发送终止信号,最多等待 30 秒直到进程退出,然后删除 pid 文件。如果 bin/pid 不存在,脚本会提示并正常退出。

6 分布式集群的启动顺序

请按以下顺序启动各组件:

  1. 全部 PD 节点。它们组成 Raft 组并选出 leader。对每个节点检查 GET /v1/ready;仅当 HTTP 状态为 200 且响应中的 ready 为 true 时,再启动 Store。GET /v1/health 只检查 REST 监听器是否存活。
  2. 全部 Store 节点。每个 Store 通过 gRPC 向 PD 注册,PD 会自动激活 pd.initial-store-list 中列出的 Store。等到 GET /v1/stores 中每个 Store 的 state 都是 Up 再继续。
  3. 全部 Server 节点。Server 读取 pd.peers,并依赖 PD 报告至少有一个存活的 Store 才能完成分区分配。
sequenceDiagram
    participant 运维者
    participant PD
    participant Store
    participant Server
    运维者->>PD: GET /v1/ready(逐个检查 PD)
    PD-->>运维者: 200 且 ready=true
    运维者->>Store: 启动 Store
    Store->>PD: gRPC 注册与心跳
    运维者->>PD: GET /v1/stores(Basic 认证)
    PD-->>运维者: 每个目标 Store 状态为 Up
    运维者->>Server: 启动 Server
    Server->>PD: gRPC 查询分区与服务发现
    Server->>Store: gRPC 访问图数据

主线 Compose 中 Store 的 depends_on: condition: service_healthy 只等待 PD /v1/health 存活检查,Server 同样只等待 Store REST 存活检查;Server entrypoint 还会轮询 PD /v1/stores,直到有 Store 报告 Up 才启动 HugeGraph。docker compose up --wait 因而不能替代 PD Raft 就绪与 Store 注册状态检查。

停止时顺序相反:先停 Server,再停 Store,最后停 PD。

7 验证

7.1 REST API 认证

当前主线除 /actuator/*、/v1/health、/v1/ready 和 /v1/prom/targets/* 之外,所有 PD REST 路径都要求 HTTP Basic Authorization。用户名必须是内部服务名 hg、store、hubble、vermeer 之一,密码必须等于 auth.secret-key;无密钥或密码不匹配时会返回 HTTP 401。用启动 PD 时的同一密钥检查 Store 列表:

1{"status": -1, "error": "Unauthorized"}
1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?请先设置 PD 部署密钥}" \
2  http://localhost:8620/v1/stores

bin/wait-storage.sh 通过 PD_AUTH_USER、PD_AUTH_PASSWORD 配置同一凭据。1.7.0 发布标签的认证实现只检查用户名是否属于内部服务名,不比较密码;不要把该旧版行为套用到当前主线源码构建包。

警告

生产环境分别保护 Server 与 PD 端口

生产环境的 Server 图 API 必须按 Server 认证与授权配置启用 Auth、IP 白名单和最小权限授权,并保留、保护 Server audit-*.log。这些设置不保护 PD:当前主线 PD REST 使用 auth.secret-key;1.7.0 的认证实现仅检查用户名是否属于内部服务名,不比较密码。Raft 端口应保持 raft.ip-whitelist.enabled 并只允许配置的 peer,PD REST 与 gRPC 端口也必须限制在受信网络内。PD 的 /v1/health、/v1/ready 和 Actuator 探针无需 Basic 认证,须由网络策略限制可达范围;主线默认日志配置生成的 logs/audit-hugegraph-pd.log 也须纳入日志保护。

7.2 健康检查

GET /v1/health 不需要凭据,返回 200 且响应体为空,只表示 PD REST 监听器已启动:

1curl -i http://localhost:8620/v1/health

Spring Boot actuator 端点同样可用,输出更直观:

1curl http://localhost:8620/actuator/health

/actuator/health 的 {"status":"UP"} 也不代表 PD Raft 集群已有可用 leader。主线新增的 GET /v1/ready 会在 PD Raft 节点已激活并能看到 leader 时返回 HTTP 200 和 ready:true;尚未就绪时返回 HTTP 503 和 ready:false:

1curl -i http://localhost:8620/v1/ready

7.3 集群与成员状态

查看 PD 成员以及当前的 Raft leader:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?请先设置 PD 部署密钥}" \
2  http://localhost:8620/v1/members

响应中包含 pdList、选出的 pdLeader、numOfService、numOfNormalService 和 stateCountMap。健康的 3 节点 PD 集群中,numOfService 和 numOfNormalService 都应为 3,且恰好有一个成员的 role 为 Leader。

GET /v1/cluster 在成员列表之外还返回 Store 列表、图列表和集群整体状态;GET / 返回一份简要汇总(leader 地址、集群状态、成员数、Store 数、图数量、分区数)。

7.4 Store 状态

也可以通过 PD API 查看 Store 节点状态:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?请先设置 PD 部署密钥}" \
2  http://localhost:8620/v1/stores

如果响应中 state 为 Up,说明对应的 Store 节点运行正常。下面的示例只有一个 Store 节点。在一个健康的 3 节点部署中,storeId 列表应包含 3 个 ID,且 stateCountMap.Up、numOfService 和 numOfNormalService 都应为 3。

 1{
 2  "message": "OK",
 3  "data": {
 4    "stores": [
 5      {
 6        "storeId": 8319292642220586694,
 7        "address": "127.0.0.1:8500",
 8        "raftAddress": "127.0.0.1:8510",
 9        "version": "",
10        "state": "Up",
11        "deployPath": "/Users/{your_user_name}/hugegraph/apache-hugegraph-incubating-1.7.0/apache-hugegraph-store-incubating-1.7.0/lib/hg-store-node-1.7.0.jar",
12        "dataPath": "./storage",
13        "startTimeStamp": 1754027127969,
14        "registedTimeStamp": 1754027127969,
15        "lastHeartBeat": 1754027909444,
16        "capacity": 494384795648,
17        "available": 346535829504,
18        "partitionCount": 0,
19        "graphSize": 0,
20        "keyCount": 0,
21        "leaderCount": 0,
22        "serviceName": "127.0.0.1:8500-store",
23        "serviceVersion": "",
24        "serviceCreatedTimeStamp": 1754027127000,
25        "partitions": []
26      }
27    ],
28    "stateCountMap": {
29      "Up": 1
30    },
31    "numOfService": 1,
32    "numOfNormalService": 1
33  },
34  "status": 0
35}

7.5 其他 REST 接口

下表中的路径均相对于 http://<pd-host>:8620,除注明外都需要 7.1 中的 Basic 认证头。

方法与路径描述
GET /集群简要统计:leader、状态、成员数、Store 数、图数量、分区数
GET /v1/health存活检查;HTTP 200 不代表 Raft 就绪,无需认证
GET /v1/readyRaft readiness;HTTP 200 且 ready:true 表示本节点已激活并看到 leader,无需认证(当前主线)
GET /v1/cluster集群完整统计:PD 成员、Store、图、分区
GET /v1/membersPD 成员列表,含角色和选出的 leader
POST /v1/members/change修改 Raft peer 列表,请求体 {"peerList": "..."}
GET /v1/stores已注册的 Store 节点及其状态和统计信息
GET /v1/store/{storeId}单个 Store 节点
POST /v1/store/{storeId}修改 Store 状态,请求体 {"storeState": "..."}
DELETE /v1/store/{storeId}从集群中移除 Store
POST /v1/store/logStore 状态变更日志,请求体 {"startTime": "...", "endTime": "..."}
GET /v1/storesAndStatsStore 原始元数据,用于调试
GET /v1/store_monitor/{storeId}Store 监控采样数据(文本)
GET /v1/store_monitor/json/{storeId}Store 监控采样数据(JSON)
GET /v1/shards所有分区的所有副本,含 store id、角色、状态和进度
GET /v1/shardGroupsShard 分组
GET /v1/shardGroupsCachePD 内存缓存中的 shard 分组
GET /v1/shardLeaders按 Store raft 地址分组的分区 leader
GET /v1/balanceLeaders在各 Store 之间重新平衡分区 leader
GET /v1/partitions分区列表及其状态和统计信息
GET /v1/highLevelPartitions分区列表,含各图的 key 数量和数据大小
GET /v1/partitionsAndStats分区原始元数据,用于调试
POST /v1/partitions/log分区变更日志,请求体 {"startTime": "...", "endTime": "..."}
GET /v1/resetPartitionState重置所有分区的状态
GET /v1/graphs图列表
GET /v1/graph/**按名称查询单个图
POST /v1/graph/**修改图的分区数,请求体 {"partitionCount": N}
GET /v1/graph/partitionSizeRange集群允许的分区数上下限
GET /v1/graph-spaces图空间列表
GET /v1/graph-spaces/**单个图空间
POST /v1/graph-spaces/**修改图空间
POST /v1/registry注册一个服务实例用于服务发现
POST /v1/registryInfo查询已注册的实例
GET /v1/allInfo所有已注册的实例
GET /v1/license旧接口,当前主线返回空对象
GET /v1/license/machineInfoLicense 校验看到的 IP 和 MAC 地址
GET /v1/task/patrolStores立即执行 Store 巡检任务
GET /v1/task/patrolPartitions立即执行分区巡检任务
GET /v1/task/balancePartitions在各 Store 之间重新平衡分区
GET /v1/task/splitPartitions立即执行自动分区拆分
GET /v1/task/balanceLeaders重新平衡分区 leader
GET /v1/task/compact让 Store 节点对其分区的 RocksDB 文件做 compaction
GET /v1/prom/targets/{appName}Prometheus 服务发现目标,无需认证
GET /v1/prom/targets-all所有应用类型的 Prometheus 目标
GET /v1/prom/sd_configPrometheus HTTP 服务发现配置
GET /actuator/healthSpring Boot 健康检查,无需认证
GET /actuator/metricsSpring Boot 监控指标,无需认证
GET /actuator/prometheusPrometheus 抓取端点,无需认证

两个 log 接口接受形如 {"startTime": "...", "endTime": "..."} 的时间范围,yyyy-MM-dd HH:mm:ss 和 yyyy-MM-dd 都是可接受的格式。

PD 以 hg 前缀注册自己的指标,因此 /actuator/prometheus 除标准 JVM 指标外还会暴露 hg_up、hg_graphs、hg_stores 和 hg_terms,在存在图之后还会有按图统计的分区和大小指标。

在 1.7.0 之后的版本中,PD 还会为每个已注册的 Store 导出 hg_store_state{store="<id>",state="<state>"}:Store 当前状态(Unknown、Pending、Up、Offline、Exiting 或 Tombstone)对应的序列为 1,其余为 0;以及 hg_store_leader_count{store="<id>"},即 leader 位于该 Store 上的分片组数量。重建后的 Store 在 leader 迁回之前会报告 0。所有 PD 成员读取的是同一份复制的元数据,因此聚合这些序列前请先只选取一个实例。

1.3 - HugeGraph-Store 快速上手

1 HugeGraph-Store 概述

HugeGraph-Store 是 HugeGraph 分布式版本的存储节点组件,负责实际存储和管理图数据。它与 HugeGraph-PD 协同工作,共同构成 HugeGraph 的分布式存储引擎,提供高可用性和水平扩展能力。

每个 Store 节点使用 RocksDB 保存图数据,并通过 Raft(JRaft)进行复制:每个分区是一个独立的 Raft 组,因此分区在丢失少数副本时仍可继续工作。Store 节点之间并不直接感知彼此,它们向 PD 注册,由 PD 下发分区分配,并通过心跳上报状态。HugeGraph-Server 先从 PD 查询分区位置,再通过 gRPC 访问 Store。

2 依赖

2.1 前置条件

  • 操作系统:Linux 或 macOS(Windows 尚未经过完整测试)
  • Java 版本:HugeGraph 1.8.0+ 使用 Java 17(Maven 源码构建仅接受 JDK 17;启动脚本拒绝低于 17 的运行时;1.7.0 是最后一个支持 Java 11 的版本)
  • Maven 版本:≥ 3.6.3(从源码编译时)
  • 如需进行多节点部署,请先部署 HugeGraph-PD

3 部署

有两种方式可以部署 HugeGraph-Store 组件:

  • 方式 1:下载 tar 包
  • 方式 2:源码编译

3.1 下载 tar 包

Apache 下载页目前提供 1.7.0 的完整二进制包,其中包含 PD、Store 和 Server;没有单独列出 Store 二进制包。下载前请在 官方 Apache HugeGraph 下载页核对版本、签名和 SHA512。1.7.0 是孵化期发布的历史版本,归档文件和解压目录仍带 incubating:

1# 1.7.0 是项目孵化期发布的历史版本,因此文件名和目录名仍带 incubating
2curl -fLO --connect-timeout 10 --max-time 1800 https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3tar zxf apache-hugegraph-incubating-1.7.0.tar.gz
4cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-store-incubating-1.7.0

3.2 源码编译

 1# 1. 克隆源代码
 2git clone https://github.com/apache/hugegraph.git
 3
 4# 2. 编译项目
 5cd hugegraph
 6mvn clean install -DskipTests=true
 7
 8# 3. 编译成功后,Store 目录和完整发布包分别位于
 9#    hugegraph-store/apache-hugegraph-store-{version}
10#    target/apache-hugegraph-{version}.tar.gz

如果只想单独编译 Store 而不是整个仓库,需要先编译 hugegraph-struct,因为 Store 依赖它:

1mvn install -pl hugegraph-struct -am -DskipTests
2mvn clean package -pl hugegraph-store/hg-store-dist -am -DskipTests

生成的目录只包含 bin/、conf/ 和 lib/hg-store-node-{version}.jar。

3.3 Docker 部署

HG_STORE_* 环境变量映射是当前主线源码提供的功能;server 的 1.7.0 发布源码标签尚无这些映射。本文下面的 Docker 示例仅适用于从当前主线源码构建并使用同一个本地标签的 PD、Store 和 HStore Server 镜像:

1# 在 hugegraph 仓库根目录执行
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .
3docker build -f hugegraph-store/Dockerfile -t hugegraph/store:local .
4docker build -f hugegraph-server/Dockerfile-hstore -t hugegraph/server:local .

首次启动前,按 docker/README.md 的认证环境步骤 在 docker/ 创建 .env。 该步骤使用 umask 077 并拒绝覆盖已有文件;若 .env 已存在,应保留原文件并编辑补全缺少的项。不要为已初始化的数据目录重新生成 HG_PD_AUTH_SECRET_KEY。此文件由仓库 .gitignore 忽略,仍不要提交。 每次在新 shell 执行 Compose 或 PD REST 命令前,都从 docker/ 目录加载同一文件:

1# 在 hugegraph 仓库根目录执行
2cd docker
3set -a; . ./.env; set +a
4: "${HG_PD_AUTH_SECRET_KEY:?请在 .env 中设置 HG_PD_AUTH_SECRET_KEY}"
5# 只启动 PD、Store、Server,不启动可选 Hubble 服务
6HUGEGRAPH_VERSION=local HUGEGRAPH_PULL_POLICY=never \
7  docker compose -f docker-compose-hstore.yml \
8  up -d --wait pd store server

后续重启或调用 PD REST 时,先按上面的方式加载同一个密钥;不要为已初始化的数据目录重新生成新值。HUGEGRAPH_VERSION=local 和 HUGEGRAPH_PULL_POLICY=never 是此 Compose 命令的参数,每次运行 Compose 生命周期命令时都要显式带上。

若要启动 Compose 文件中的 Hubble 服务,需使用拓扑对应的未跟踪配置文件。最小拓扑 docker-compose-hstore.yml 使用 conf/hubble/hstore.local.properties; HA 拓扑 docker-compose-3pd-3store-3server.yml 使用 conf/hubble/hstore-ha.local.properties。 上述 README 初始化步骤会用共享 PD 密钥生成两份文件。若文件缺失或需更新,先从 docker/ 目录载入已有 .env,再执行对应命令:

1set -a; . ./.env; set +a
2./set-hubble-pd-password.sh hstore      # 最小拓扑
3./set-hubble-pd-password.sh hstore-ha  # HA 拓扑

多节点拓扑中的服务名是 pd0–pd2、store0–store2 和 server0–server2。该主线 Compose 文件也应使用上述本地构建的同标签镜像,不能将 HUGEGRAPH_VERSION=1.7.0 发布镜像与主线 Compose 文件混用。

单独运行当前主线构建的 Store 时,将示例地址换成 Store 与 PD 均可路由的实际地址:

下面的 mkdir -p 和非递归 chown 仅适用于新建空目录。复用旧 root 镜像写入的数据时,先停止 Store, 执行一次 sudo chown -R 10001:10001 /path/to/storage,再启动 UID 10001 镜像。

 1# master 构建的镜像以 UID 10001 运行,宿主机数据目录必须对该用户可写
 2mkdir -p /path/to/storage && sudo chown 10001:10001 /path/to/storage
 3docker run -d \
 4  -p 8520:8520 -p 8500:8500 -p 8510:8510 \
 5  -e HG_STORE_PD_ADDRESS=192.168.1.10:8686 \
 6  -e HG_STORE_GRPC_HOST=192.168.1.20 \
 7  -e HG_STORE_RAFT_ADDRESS=192.168.1.20:8510 \
 8  -v /path/to/storage:/hugegraph-store/storage \
 9  --name hugegraph-store \
10  hugegraph/store:local

当前主线 Docker 环境变量:

变量必填默认值对应配置项描述
HG_STORE_PD_ADDRESS是无pdserver.addressPD gRPC 地址,多个地址用逗号分隔。
HG_STORE_GRPC_HOST是无grpc.host本节点对外公布的 gRPC 主机名/IP;容器网络中应使用容器主机名。
HG_STORE_RAFT_ADDRESS是无raft.address本节点的 Raft 地址。
HG_STORE_GRPC_PORT否8500grpc.portgRPC 服务端口。
HG_STORE_REST_PORT否8520server.portREST API 端口。
HG_STORE_DATA_PATH否/hugegraph-store/storageapp.data-path数据存储路径。

当前主线 entrypoint 将这些变量写入 SPRING_APPLICATION_JSON,覆盖镜像内 conf/application.yml;其余配置仍从该文件和 application-pd.yml 读取,然后以前台方式启动 Java。旧变量 PD_ADDRESS、GRPC_HOST、RAFT_ADDRESS 仍可用,但会输出弃用警告。

PD 和 Store 的 Docker HEALTHCHECK 都检查 /v1/health,只说明本地 REST 监听器有响应。Compose 的 depends_on 也以此作为启动门槛,因此还需单独检查 PD /v1/ready 与 PD /v1/stores 中的 Store Up 状态。Store 镜像默认设置 STDOUT_MODE=true;其 Dockerfile 只声明 EXPOSE 8520,从 Docker 网络外访问 gRPC 8500 或 Raft 8510 时需另行发布端口。

4 配置

Store 从 conf/ 读取两个配置文件。1.7.0 发布标签的源文件见 application.yml 和 application-pd.yml;当前主线文件见 application.yml 和 application-pd.yml。主线默认配置把 spring.profiles.include: pd 加载的 RocksDB 设置放在第二个文件中;启动脚本指定 application.yml。

  • application.yml,主配置文件(PD 地址、各端口、Raft、数据路径)
  • application-pd.yml,由 application.yml 中的 spring.profiles.include: pd 引入,包含 RocksDB 内存设置和 Actuator 暴露配置

4.1 application.yml

以下配置参考表核对的是 server 主线提交 2f827d6e8c9c62ae858f2fc122b3a192d015e2f4 的发行目录值和 Java 默认注入值;1.7.0 发布包请使用其版本标签对应的配置文件,不要跨版本覆盖。

4.2 application-pd.yml

此文件只保存 rocksdb 参数和 Actuator 暴露设置。

警告

生产环境分别保护 Server 与 Store 端口

生产环境的 Server 图 API 必须按 Server 认证与授权配置启用 Auth、IP 白名单和最小权限授权,并保留、保护 Server audit-*.log。这些设置不保护 Store:主线默认配置暴露所有 Actuator 端点,且没有 PD 式 Basic 认证保护;必须将 Store REST、gRPC 和 Raft 端口限制在集群与受信运维网络内。

4.3 配置项参考

下表中「当前主线目录值」来自前述两个主线配置文件,「代码默认值」是配置项缺失时节点使用的回退值;目录中未列出的配置项应以代码默认值为准。

核心

配置项当前主线目录值代码默认值说明
pdserver.addresslocalhost:8686必填PD gRPC 地址,多个地址用逗号分隔。Store 在此注册并获取分区分配。必须填写 PD 的 grpc.port,不是 PD 的 REST 端口。
grpc.host127.0.0.1必填本节点对外公布的 gRPC 地址。应设置为可路由的 IP 或主机名,127.0.0.1 只适用于单机部署。
grpc.port8500必填gRPC 端口,Server 和 Store 客户端连接此端口。
grpc.netty-server.max-inbound-message-size1000MBgRPC 默认值单个入站 gRPC 消息的最大大小,由 grpc-spring-boot-starter 的 Netty 服务端读取。
grpc.server.wait-time未设置3600扫描流等待客户端消费一页数据的秒数,超时后服务端中止该流。
server.port8520必填REST 和 Actuator 端口,同时以 rest.port 标签上报给 PD。

Raft

配置项当前主线目录值代码默认值说明
raft.address127.0.0.1:8510必填本节点的 Raft 服务地址,格式为 host:port,必须能被其他 Store 节点访问。这里不需要配置 peer 列表:分区 Raft 组的成员由 PD 下发。
raft.disruptorBufferSize10240Raft 任务队列大小。设为 0 时按 rocksdb.total_memory_size 推导:将该内存量的 GB 数取最接近的 2 的幂,再乘以 32。
raft.max-log-file-size60000000000050000000000Raft 日志的最大字节数。
raft.snapshotInterval1800300生成 Raft 快照的时间间隔,单位秒。
raft.snapshotLogIndexMargin未设置0距上次快照的最小 applied index 差值,达到后才真正生成快照。设为 0 关闭该判断。
raft.rpc-timeout未设置10000Raft RPC 超时时间,单位毫秒。
raft.metrics未设置true采集 JRaft 节点指标,可通过 /metrics/raft 读取。
raft.useRocksDBSegmentLogStorage未设置true使用 RocksDB 分段日志存储保存 Raft 日志。
raft.maxSegmentFileSize未设置67108864分段日志文件大小,单位字节(64 MB)。
raft.maxReplicatorInflightMsgs未设置256每个 follower 的最大在途复制请求数。
raft.maxEntriesSize未设置256单次 AppendEntries 请求包含的最大条目数。
raft.maxBodySize未设置524288单次 AppendEntries 请求的最大字节数。
ave-logEntry-size-ratio未设置0.95估算日志条目平均大小时的平滑系数。注意该配置项位于顶层,不在 raft 下。

存储与标签

配置项当前主线目录值代码默认值说明
app.data-path./storagestoreRocksDB 数据目录。用逗号分隔多个路径可将分区分散到多块磁盘。
app.raft-path已注释空Raft 日志和快照目录。为空时回退到 app.data-path。
app.fake-pd未设置false内置 PD 模式,仅用于单机测试,不要用于生产。
app.placeholder-size未设置10启动时在每个数据路径下创建的 placeholder 占位文件大小,单位 GB,便于紧急情况下释放空间。设为 0 关闭。
app.label.<name>未设置无随 store 心跳上报给 PD 的自定义键值标签。节点会自动追加 rest.port。

RocksDB

配置项当前主线目录值代码默认值说明
rocksdb.total_memory_size3200000000051539607552本节点所有 RocksDB 实例共享的内存预算。缺失或为 0 时使用 JVM 最大堆内存。
rocksdb.write_buffer_size3200000033554432memtable 大小,单位字节。缺失或为 0 时取 total_memory_size / 1000。
rocksdb.min_write_buffer_number_to_merge1616落盘前合并的 memtable 数量。
rocksdb.write_buffer_ratio未设置0.66total_memory_size 中分配给写缓存的比例,其余作为 block cache。

org/apache/hugegraph/rocksdb/access/RocksDBOptions.java 中定义的其他选项都可以加在同一个 rocksdb: 块下,例如 rocksdb.max_background_jobs、rocksdb.level0_file_num_compaction_trigger 或 rocksdb.bloom_filter_bits_per_key。

线程池

配置项代码默认值说明
thread.pool.grpc.core600处理 gRPC 请求的核心线程数。
thread.pool.grpc.max1000gRPC 最大线程数。
thread.pool.grpc.queue2147483647gRPC 任务队列容量。
thread.pool.scan.core128处理扫描的核心线程数。设为 0 时取 CPU 核数的 4 倍。
thread.pool.scan.max1000扫描最大线程数。
thread.pool.scan.queue0扫描任务队列容量。

gRPC 回调队列(1.8.0)

Store 使用无界队列处理 gRPC 回调,避免队列满时丢弃取消或完成通知,导致请求无法正常结束。thread.pool.grpc.queue 仍可写在配置中,但不再限制这个队列的容量。

thread.pool.grpc.core 和 thread.pool.grpc.max 仍用于配置线程池。由于回调可以继续排队,积压通常不会触发线程数从 core 增长到 max;只增大 max 无法提高回调处理能力。

持续过载仍会使队列积压并增加内存占用。应限制客户端并发,并根据节点资源调整扫描和查询工作线程池;不要依赖 thread.pool.grpc.queue 限流。1.7.0 仍使用配置的 gRPC 队列容量。

查询下推

配置项代码默认值说明
query.push-down.threads1500下推查询的线程池大小。
query.push-down.fetch_batch20000单次请求拉取的行数。
query.push-down.fetch_timeout300000拉取超时时间,单位毫秒。
query.push-down.memory_limit_count50000排序等内存操作的行数上限。
query.push-down.index_size_limit_count50000索引 sst 文件大小上限,单位 kB。

后台任务

配置项代码默认值说明
job.interruptableThreadPool.core128TTL 清理线程池的核心线程数。设为 0 时取 CPU 核数。
job.interruptableThreadPool.max256TTL 清理线程池的最大线程数。设为 0 时取 CPU 核数的 4 倍。
job.interruptableThreadPool.queue2147483647TTL 清理线程池的队列容量。
job.uninterruptibleThreadPool.core0存储引擎不可中断任务线程池的核心线程数。设为 0 时取 CPU 核数。
job.uninterruptibleThreadPool.max256不可中断任务线程池的最大线程数。
job.uninterruptibleThreadPool.queue2147483647不可中断任务线程池的队列容量。
job.cleaner.batch.size10000TTL 清理任务每批删除的 key 数量。
job.start-time0每日 TTL 清理执行的小时数(0 到 23)。超出该范围时回退为 19。

内置 PD 模式

仅用于单机开发调试,通过 app.fake-pd: true 开启。此时节点自行扮演 PD 角色,并忽略 pdserver.address。

配置项代码默认值说明
fake-pd.store-list''伪集群中各 Store 节点的 gRPC 地址。
fake-pd.peers-list''同一批节点的 Raft 地址。
fake-pd.partition-count3分区数量。
fake-pd.shard-count3每个分区的副本数。

诊断

自 HugeGraph 1.8.0 起,Store 的 HTTP 激活接口 GET /v1/arthasstart 已禁用(直接返回 403),旧 Arthas 配置字段仅为兼容保留。 推荐直接以服务进程属主身份运行发行包内置的脚本诊断正在运行的 JVM (官方容器镜像内置 JDK 17,可直接使用 docker exec 执行):

1bin/arthas.sh

同机多进程时可指定 --pid <PID> --telnet-port 3659。 更多参数、认证配置及安全实践参见 Arthas 诊断代理。

4.4 各节点需要区分的配置

对于多节点部署,需要为每个 Store 节点修改以下配置:

  1. grpc.host 和 grpc.port(其他组件访问本节点的地址)
  2. raft.address(Raft 协议地址)
  3. server.port(REST 端口)
  4. app.data-path(数据存储路径)

pdserver.address 在所有节点上保持一致,它列出的是整个 PD 集群。

5 启动与停止

5.1 启动 Store

确保 PD 服务已经启动,然后在 Store 安装目录下执行:

1./bin/start-hugegraph-store.sh

下文的生命周期与下载时限说明适用于包含启动脚本修复的 master 构建;上文下载的 1.7.0 启动脚本不包含这些修复。 启动脚本支持四个参数,GC 的版本限制见下文:

参数取值默认值说明
-dtrue、falsetrue守护进程模式,见下文。
-g见下文版本限制未设置选择垃圾回收器;不支持的参数会中止启动。
-jJVM 参数字符串空附加的 JVM 参数,例如 -j "-Xmx16g -Xms8g"。
-ytrue、falsefalse挂载 OpenTelemetry Java agent(首次使用时下载到 plugins/),并将 trace 导出到 127.0.0.1:4317。

master 构建接受 g1、G1、zgc 和 ZGC。 上文下载的 1.7.0 启动脚本仅接受显式指定 zgc 或 ZGC;-g g1、-g G1 和其他参数会中止启动。 默认路径请省略 -g;参数被拒绝时,查看 logs/hugegraph-store-server.log。

守护进程模式:

  • -d true(默认):以后台守护进程方式运行,脚本立即返回,并把 Java 进程号写入 bin/pid。
  • -d false:以前台模式运行,脚本通过 exec 替换为 Java 进程,容器或进程管理器的进程即为 Java 本身。在 Docker 或进程管理器(systemd、supervisord)下运行时请使用此参数,以便在崩溃时自动检测并重启服务。

JVM 内存方面,如果没有自行设置 JAVA_OPTIONS:-Xms512m,-Xmx 取空闲内存的一半并限制在 512 MB 到 2048 MB 之间。脚本还会加上 -XX:MetaspaceSize=256M、OOM 时把堆转储写入 logs/,以及滚动的 GC 日志 logs/gc.log。生产节点通常需要大得多的堆,请显式指定,例如 -j "-Xmx32g -Xms32g"。

当 ulimit -n 或 ulimit -u 低于 1024 时脚本会拒绝启动;在 x86_64 和 arm64 上,如果能成功下载并校验对应的动态库,脚本会预加载 jemalloc。

主线构建中,每次可选 jemalloc 下载的连接时限为 5 秒,总时限为 30 秒。 1.7.0 的下载 helper 没有连接或总时限。超时或校验失败时沿用已有回退路径,不预加载下载库并继续启动。 校验有效的缓存库仍可复用,失败下载的临时文件会被清理。

启动成功后,可以在 logs/hugegraph-store-server.log 中看到类似以下的日志:

1YYYY-mm-dd xx:xx:xx [main] [INFO] o.a.h.s.n.StoreNodeApplication - Started StoreNodeApplication in x.xxx seconds (JVM running for x.xxx)

5.2 停止 Store

在 Store 安装目录下执行:

1./bin/stop-hugegraph-store.sh

脚本读取 bin/pid,向该进程发送信号,最多等待 30 秒直至进程退出,然后删除 pid 文件。如果 bin/pid 不存在,脚本直接退出且不做任何操作。

5.3 重启 Store

1./bin/restart-hugegraph-store.sh

该脚本依次 source 停止脚本和启动脚本,并转发 5.1 中的参数。

5.4 启动顺序

  1. 先启动全部 PD 节点。每个 Store 的 grpc.host:grpc.port 都应出现在 PD 的 pd.initial-store-list 中,否则 PD 只会把该节点登记为 Pending 而不会置为 Up,分区分配也就无法完成。当前主线应先对每个 PD 检查 /v1/ready 返回 HTTP 200 且 ready:true;/v1/health 只是存活检查。
  2. 再启动 Store。Store 早于 PD 启动并不致命:心跳线程会持续重试注册,并在 PD 可用之前打印 store heartbeat error: PD UNREACHABLE。
  3. 最后启动 HugeGraph-Server,此时所有 Store 节点都应上报 state: "Up"。Server 需要分区就绪之后才能初始化或打开图。

主线 Compose 用 depends_on: condition: service_healthy 等待本地健康检查,但 PD 和 Store 的 Docker 健康检查都只访问 /v1/health,不能证明 Raft 多数派或 Store 注册已就绪。Server entrypoint 会等待 PD 至少报告一个 Up 的 Store;运维时仍应检查 PD /v1/ready 和 /v1/stores。

6 多节点部署示例

以下是一个三节点部署的配置示例:

6.1 三节点配置参考

  • 3 PD 节点
    • raft 端口:8610, 8611, 8612
    • rpc 端口:8686, 8687, 8688
    • rest 端口:8620, 8621, 8622
  • 3 Store 节点
    • raft 端口:8510, 8511, 8512
    • rpc 端口:8500, 8501, 8502
    • rest 端口:8520, 8521, 8522

6.2 Store 节点配置

对于三个 Store 节点,每个节点的主要配置差异如下:

节点 A:

1grpc:
2  port: 8500
3raft:
4  address: 127.0.0.1:8510
5server:
6  port: 8520
7app:
8  data-path: ./storage-a

节点 B:

1grpc:
2  port: 8501
3raft:
4  address: 127.0.0.1:8511
5server:
6  port: 8521
7app:
8  data-path: ./storage-b

节点 C:

1grpc:
2  port: 8502
3raft:
4  address: 127.0.0.1:8512
5server:
6  port: 8522
7app:
8  data-path: ./storage-c

所有节点都应该指向相同的 PD 集群:

1pdserver:
2  address: 127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688

同时每个 PD 节点都应列出三个 Store 的 gRPC 地址:

1pd:
2  initial-store-list: 127.0.0.1:8500,127.0.0.1:8501,127.0.0.1:8502

6.3 Docker 分布式集群配置

3 节点 Store 集群包含在 docker/docker-compose-3pd-3store-3server.yml 中。每个 Store 节点拥有独立的主机名和环境变量:

 1# store0,宿主机端口 8500(gRPC)、8510(Raft)、8520(REST)
 2HG_STORE_PD_ADDRESS: pd0:8686,pd1:8686,pd2:8686
 3HG_STORE_GRPC_HOST: store0
 4HG_STORE_GRPC_PORT: "8500"
 5HG_STORE_REST_PORT: "8520"
 6HG_STORE_RAFT_ADDRESS: store0:8510
 7HG_STORE_DATA_PATH: /hugegraph-store/storage
 8
 9# store1,宿主机端口 8501、8511、8521
10HG_STORE_GRPC_HOST: store1
11HG_STORE_RAFT_ADDRESS: store1:8510
12
13# store2,宿主机端口 8502、8512、8522
14HG_STORE_GRPC_HOST: store2
15HG_STORE_RAFT_ADDRESS: store2:8510

每个节点的容器内端口都是 8500/8510/8520,只有映射到宿主机的端口不同。PD 节点相应地设置 HG_PD_INITIAL_STORE_LIST: store0:8500,store1:8500,store2:8500。

Store 节点仅在所有 PD 节点通过健康检查后才会启动,其中 docker-compose 中的 healthcheck 实际访问的是 PD 的 REST 接口 /v1/health(也可以通过 Actuator 暴露的 /actuator/health 进行手动检查),并通过 depends_on: condition: service_healthy 强制执行依赖关系。

运行时日志可通过 docker logs <container-name>(如 docker logs hg-store0)直接查看,无需进入容器。

完整的部署指南请参阅 docker/README.md。

7 验证 Store 服务

确认 Store 服务是否正常运行:

1curl http://localhost:8520/actuator/health

如果返回 {"status":"UP"},表示 Store 本地应用健康检查通过;它本身不证明已在 PD 注册为 Up。

GET /v1/health 是 Docker 镜像和 compose 文件使用的轻量检查接口,它返回 HTTP 200 且响应体为空,因此应使用 curl -fsS 并检查退出码,而不是检查输出内容:

1curl -fsS http://localhost:8520/v1/health && echo OK

7.1 Store REST 接口

Store 节点在 server.port 上提供以下只读接口:

方法路径描述
GET/v1/health存活探测,HTTP 200 且响应体为空
GET/actuator/healthSpring Boot Actuator 健康检查,返回 {"status":"UP"}
GET/actuator/prometheusPrometheus 抓取接口
GET/节点概览,包含 leaderCount 和 partitionCount
GET/-/state运维设置的节点状态标志,取值为 STARTING、ONLINE、STOPPING;此标志不表示 PD 注册状态
GET/-/echo?name=<text>回显检查
GET/-/scan当前扫描流的状态
GET/v1/partitions本节点上的所有 Raft 组及分区指标。加上 ?flags=accurate 可获取精确的 key 数量,但更慢。
GET/v1/partition/{id}按分区 id 查询单个 Raft 组,包含角色、leader、peers 和已提交索引
GET/metrics/system主机 CPU 和内存指标
GET/metrics/drive数据路径所在磁盘的指标
GET/metrics/raftJRaft 节点指标,需要 raft.metrics: true

主线发行目录的 Store 配置将 management.endpoints.web.exposure.include 设为 "*",并启用 Prometheus;Actuator 端点没有 PD REST Basic 认证保护,请限制 Store REST 端口的网络可达范围。

节点还提供一批会修改状态或执行重负载操作的运维接口:PUT /-/state、GET /-/cleaner、GET /v1/partition/dump/{id}、 GET /v1/partition/clean/{id}、POST /v1/compat?id=<partition>、POST /raft/options,以及 /fix/* 和 /test/* 两组接口。 请仅在排查问题时使用,并且不要把 REST 端口暴露到不可信网络。

7.2 通过 PD 检查注册结果

也可以通过 PD API 查看集群中的 Store 节点状态:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?请先设置 PD 部署密钥}" \
2  http://localhost:8620/v1/stores

对于当前主线源码构建包,PD REST 用户名必须是 hg、store、hubble、vermeer 之一,密码必须与 PD 的 auth.secret-key 相同;HG_PD_AUTH_SECRET_KEY 会同时配置 Compose 中的 PD 和 Server。/v1/health、/v1/ready、/actuator/* 和 /v1/prom/targets/* 不需要认证。1.7.0 发布标签的实现只校验用户名,不比较密码;不要把这一旧行为用于主线源码构建包。

如果 Store 配置成功,上述接口响应中应包含当前节点的状态信息,其中 state 为 Up 表示节点运行正常。如果节点长期停留在 Pending,通常是因为它没有出现在 PD 的 pd.initial-store-list 中。

下方示例仅展示 1 个 Store 节点的返回结果。如果 3 个节点都已正确配置并正在运行,则响应中的 storeId 列表应包含 3 个 ID,且 stateCountMap.Up、numOfService 和 numOfNormalService 都应为 3。

 1{
 2  "message": "OK",
 3  "data": {
 4    "stores": [
 5      {
 6        "storeId": 8319292642220586694,
 7        "address": "127.0.0.1:8500",
 8        "raftAddress": "127.0.0.1:8510",
 9        "version": "",
10        "state": "Up",
11        "deployPath": "/Users/{your_user_name}/hugegraph/hugegraph-store/apache-hugegraph-store-{version}/lib/hg-store-node-{version}.jar",
12        "dataPath": "./storage",
13        "startTimeStamp": 1754027127969,
14        "registedTimeStamp": 1754027127969,
15        "lastHeartBeat": 1754027909444,
16        "capacity": 494384795648,
17        "available": 346535829504,
18        "partitionCount": 0,
19        "graphSize": 0,
20        "keyCount": 0,
21        "leaderCount": 0,
22        "serviceName": "127.0.0.1:8500-store",
23        "serviceVersion": "",
24        "serviceCreatedTimeStamp": 1754027127000,
25        "partitions": []
26      }
27    ],
28    "stateCountMap": {
29      "Up": 1
30    },
31    "numOfService": 1,
32    "numOfNormalService": 1
33  },
34  "status": 0
35}

7.3 最小图读写验证

确认 Store 已在 PD 中显示为 Up 后,再启动配置为 HStore 后端、连接同一 PD 集群的 Server。Server 配置步骤见 Server 快速上手。确认 GET /versions 可访问且默认图 hugegraph 已加载后,可以创建一个属性键、顶点标签和顶点,再读取该顶点:

 1SERVER_URL=http://localhost:8080
 2GRAPH_URL="$SERVER_URL/graphspaces/DEFAULT/graphs/hugegraph"
 3
 4# 这些名称在当前图空间中必须唯一;已存在时换一组名称再执行
 5curl -fsS -X POST "$GRAPH_URL/schema/propertykeys" \
 6  -H 'Content-Type: application/json' \
 7  -d '{"name":"pd_store_demo_name","data_type":"TEXT","cardinality":"SINGLE","properties":[]}'
 8
 9curl -fsS -X POST "$GRAPH_URL/schema/vertexlabels" \
10  -H 'Content-Type: application/json' \
11  -d '{"name":"pd_store_demo_vertex","id_strategy":"CUSTOMIZE_STRING","properties":["pd_store_demo_name"],"primary_keys":[],"nullable_keys":[]}'
12
13curl -fsS -X POST "$GRAPH_URL/graph/vertices" \
14  -H 'Content-Type: application/json' \
15  -d '{"id":"pd-store-demo-1","label":"pd_store_demo_vertex","properties":{"pd_store_demo_name":"stored in HStore"}}'
16
17curl -fsS "$GRAPH_URL/graph/vertices/%22pd-store-demo-1%22"

最后一个响应应包含顶点 ID pd-store-demo-1 和属性 pd_store_demo_name。若 Server 开启了认证,以上请求还需按其认证配置增加凭据。

1.4 - 使用 Helm 部署 HugeGraph

本文适用于 HugeGraph 1.8.0 及以后版本,需要支持 OCI 的 Helm 3.10+ 和 Kubernetes (K8s) 1.23+。 可从 GHCR 或 Docker Hub 安装 hugegraph-helm。Chart 与 HugeGraph 服务分别维护版本,例如 0.4.x 的 Chart 可以部署 1.8.x 的服务。

警告

当前开发 Chart 的 HugeGraph 基础组件使用 latest 镜像,适合测试。 可选 Vermeer 已固定为经过验证的已发布镜像及 digest,见可选引擎。 对应 HugeGraph 服务正式发布后,生产环境请选择稳定 Chart,并检查其中的镜像版本。 镜像标签可能变化;需要固定镜像内容时,请配置各组件的 image.digest。

Artifact Hub 方便查找 Chart、查看版本和安装说明,实际安装包仍从 GHCR 或 Docker Hub 下载。 参数和源码开发方式见 chart README, 生命周期操作见 运维参考。

在 Artifact Hub 选择版本,从 GHCR 或 Docker Hub 下载 Chart,再使用 Helm 安装到 Kubernetes

1 安装

说明

默认部署规格与存储要求

  • 拓扑组成:默认部署 3 PD + 3 Store + 3 Server 与 1 Hubble,默认开启鉴权与持久化存储。
  • 存储依赖:需要集群具备默认动态 StorageClass 或预先匹配的静态 local PV,共需 7 个持久卷(3 个 10 GiB PD 卷、3 个 50 GiB Store 卷、1 个 1 GiB Hubble 卷)。
  • 内存考量:保留镜像内 JVM 内存自动推导;按需调整 resource requests/limits,确保宿主机给 9 个图服务 JVM 与 Hubble 提供足够内存。

选择一个下载源即可,公共 CI 推荐 GHCR。本地轻量测试可直接使用单节点预设。

提示

--devel 按版本号选择最新 Chart,包含开发版和稳定版,不限于某个版本系列。 生产部署或需要复现时,将 --devel 换成 --version <已发布版本>,固定你选定的版本。

GHCR(推荐)
1CHART=oci://ghcr.io/hugegraph/hugegraph-helm
2kubectl config current-context
3kubectl get nodes
4kubectl get storageclass
5helm install hugegraph "$CHART" --devel -n hugegraph \
6  --create-namespace --wait --timeout 15m
Docker Hub
1CHART=oci://registry-1.docker.io/hugegraph/hugegraph-helm
2kubectl config current-context
3kubectl get nodes
4kubectl get storageclass
5helm install hugegraph "$CHART" --devel -n hugegraph \
6  --create-namespace --wait --timeout 15m
单节点试用
1# 适合本地 Minikube/Kind 等轻量测试;直接安装本次下载的 Chart
2CHART=oci://ghcr.io/hugegraph/hugegraph-helm
3helm pull "$CHART" --devel --untar
4helm install hugegraph ./hugegraph-helm -n hugegraph \
5  -f ./hugegraph-helm/values-single.yaml \
6  --create-namespace --wait --timeout 10m

单节点试用预设使用 HStore 的 1 PD + 1 Store + 1 Server 与 Hubble,放宽调度限制,适合资源受限环境。 SeaTunnel 和 Vermeer 仍保持关闭。

2 模式和访问入口

解压后目录为 hugegraph-helm/,源码目录仍为 helm/hugegraph/。

HugeGraph Helm 核心文件与结构

  • hugegraph-helm/
    • Chart.yamlChart 元数据与版本定义
    • values.yaml默认配置(easy 模式:3 PD + 3 Store + 3 Server + 1 Hubble,NodePort 入口)
    • values-single.yaml单节点预设(本地 Minikube/Kind 测试,1 副本且关闭反亲和与 PDB)
    • values-cluster.yaml生产集群预设(跨节点反亲和调度,Store 采用 OnDelete 逐个滚动升级)
    • values-strict.yaml安全加固预设(strict 模式:全部 ClusterIP,强制启用 NetworkPolicy 隔离)
    • values.schema.jsonvalues 配置参数校验规范
    • templates/Kubernetes 资源编排模板
      • pd-statefulset.yamlPD 服务有状态副本集(元数据与调度中心)
      • store-statefulset.yamlStore 存储节点有状态副本集(分布式存储引擎)
      • server-deployment.yamlServer 引擎无状态 Deployment(注入 serviceId / graphSpace)
      • hubble-deployment.yaml可视化控制台 Deployment
      • tests/冒烟验证测试钩子(helm test,支持自定义 testGraphAlias)
    • examples/部署示例(local PV、GitOps 凭据、可选引擎、Ingress 等)
    • docs/operations.md生命周期进阶运维与故障恢复手册

默认 mode: easy,Server 和 Hubble 自动分配 NodePort,PD 保持 ClusterIP。可以直接使用 HTTP,无需域名、证书或额外确认参数。 mode: strict 默认将 Server/Hubble 设为 ClusterIP,并开启完整 NetworkPolicy 隔离。 SeaTunnel 和 Vermeer 启用后的原生 HTTP/UI 在 easy 模式下默认使用 NodePort,strict 模式下默认使用 ClusterIP,两种模式均需登录。 内部 RPC、Worker HTTP 与 SeaTunnel 成员端口仍保持私有。两个模式都保留鉴权和持久化。 优先级是组件显式参数高于全局参数,全局参数高于模式默认值,显式 false 也会生效。 全局参数包括 persistence.enabled 和 global.imageRegistry,严格预设为 values-strict.yaml。

入口访问方式前提
NodePorthttp://<可达节点IP>:<分配的NodePort>节点网络可达且防火墙放行,无需额外控制器
ClusterIP集群内虚拟 Service IP/DNS,如 hugegraph-server.hugegraph.svc:8080集群外通过 port-forward 或已有网关访问
LoadBalancer基础设施分配的地址集群有对应负载均衡控制器
Ingress通过控制器路由 HTTP 请求已安装 Ingress 控制器,域名和 TLS 都可选
1kubectl -n hugegraph get svc hugegraph-server hugegraph-hubble
2kubectl get nodes -o wide
3kubectl -n hugegraph get secret hugegraph-admin \
4  -o jsonpath='{.data.password}' | base64 --decode

使用 Hubble 的 NodePort 打开页面,以 admin 和查出的密码登录。 默认 externalTrafficPolicy: Cluster 下,访问的节点不必运行目标 Pod。ClusterIP 是集群内部的虚拟服务地址,不是节点 IP,普通笔记本通常不能直接访问。 也可以运行 kubectl -n hugegraph port-forward svc/hugegraph-hubble 8088:8088,在本机打开 http://127.0.0.1:8088。

基础 PD/Server/Hubble 三类客户端 Service 支持 externalTrafficPolicy、loadBalancerClass、loadBalancerIP、loadBalancerSourceRanges、externalIPs 和 allocateLoadBalancerNodePorts,具体行为取决于集群及负载均衡实现。LoadBalancer 专用字段应配合对应类型使用。 NodePort 省略或设为 0 时自动分配,固定端口由 Kubernetes 根据集群配置的范围校验,chart 不再强制 30000–32767。 原 HTTP 暴露确认参数保留兼容,但不再阻止渲染。

可选引擎:默认关闭

Chart 默认仅部署核心图服务(PD + Store + Server + Hubble)。针对数据集成与超大规模内存图计算场景,Chart 提供了 SeaTunnel 与 Vermeer 两款原生可选引擎,默认均保持关闭:

可选引擎默认状态核心用途运行模式 (*.mode)访问控制
Hubble开启 (true)图数据可视化、多图空间与任务监控单副本 Deployment跟随全局 mode(NodePort 或 ClusterIP)
SeaTunnel关闭 (false)异构数据源批流导入与跨图整库迁移standalone / clustereasy 为 NodePort,strict 为 ClusterIP;HTTP Basic 鉴权
Vermeer关闭 (false)内存优先的高性能分布式图计算算法standalone / clustereasy 为 NodePort,strict 为 ClusterIP;Token 鉴权,Hubble 自动集成

在 values 中将对应引擎的 enabled 设为 true 即可启用,管理密码与 Server 独立生成。 seatunnel.service.type 和 vermeer.service.type 为 null 时继承模式默认值:easy 为 NodePort,strict 为 ClusterIP。 显式 ClusterIP 保持私有;显式 NodePort(包括 strict 模式)开放需要登录的 HTTP/UI。 旧配置显式指定了 ClusterIP 时,需改回 null 才会继承 easy 默认值;省略 service.nodePort 或设为 null 时由 Kubernetes 分配端口。 引擎的 standalone / cluster 拓扑独立于上述访问设置。

SeaTunnel:按需开启原生数据导入、导出与迁移
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  --set seatunnel.enabled=true --set seatunnel.mode=standalone \
4  --wait --timeout 30m
  • 运行模式:standalone 启动 1 个 Hybrid 节点(轻量测试);cluster 模式启动多个同构节点(高并发批处理)。

  • 访问与凭据:easy 模式通过分配的 HTTP NodePort 打开 http://<可达节点IP>:<NodePort>/#/overview:

    1kubectl -n hugegraph get svc hugegraph-seatunnel \
    2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
    3kubectl get nodes -o wide

    使用 HTTP Basic 用户名 admin 和 hugegraph-seatunnel-auth Secret 中的密码登录。 strict 默认 ClusterIP,可用 kubectl -n hugegraph port-forward svc/hugegraph-seatunnel 8081:8080 在本机访问;5801 仍仅供内部通信。

  • 完整作业配置、内置示例验证及跨图迁移流程见 SeaTunnel 部署章节 或 SeaTunnel 部署指南。

Vermeer:按需开启内存图计算,自动接入 Hubble
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  --set vermeer.enabled=true --set vermeer.mode=standalone \
4  --wait --timeout 20m
1hugegraph-helm/
2  examples/
3    values-vermeer-standalone.yaml # 单机预设(单个 Pod 同时包含 Master 与 Worker)
4    values-vermeer-cluster.yaml    # 集群预设(1 个 Master Pod + 3 个 Worker Pods)
5  docs/
6    vermeer.md                     # Vermeer 算法调用、参数映射与进阶运维手册
  • 运行模式:standalone 单机模式在同一个 Pod 中运行 Master 协调与 Worker 计算容器;cluster 模式提供独立的 Master Pod 与可水平扩展的 Worker Pod 集群(默认 3 副本)。

  • Hubble 一键集成:Hubble 会自动注入 Master 内部 Service 地址与访问令牌。管理员在 Hubble 控制台即可直接触发 15+ 种图算法,计算结果保留在内存副本中,不污染原图属性。

  • 原生控制台直连:easy 模式通过 <release>-vermeer-master 分配的 HTTP NodePort 打开 http://<可达节点IP>:<NodePort>/:

    1kubectl -n hugegraph get svc hugegraph-vermeer-master \
    2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
    3kubectl get nodes -o wide

    并在 Admin credential 输入框中填入 <release>-vermeer-admin Secret 的 password(无需用户名)登录。 strict 模式默认 ClusterIP,可用 kubectl -n hugegraph port-forward svc/hugegraph-vermeer-master 6688:6688 转发访问;内部 Master/Worker RPC 与 Worker HTTP 保持私有。

  • 镜像固定策略与进阶凭据管理见 Vermeer 部署指南。

PD 元数据命名空间

顶层参数 metadataCluster(默认 hg-test)定义了 PD 中元数据的集群前缀。Chart 会将该值同步注入 Server 的 HG_SERVER_CLUSTER 与 Store 的 PD_CLUSTER,使得 Store 在接收 Vermeer 扫描请求时能准确定位 Server 写入的 Schema。

重要

metadataCluster 是元数据存储的前缀空间,而非 Raft 分组名。修改该值不会自动迁移已有图数据。开启 Vermeer 时必须保留原有集群的前缀值;若加载图时遇到 Schema missing 或 no such vertex label,请优先检查各组件的元数据前缀是否一致。自定义前缀的核验流程请参考 元数据命名空间运维指引。

服务身份与图空间

默认 server.serviceId 与 server.graphSpace 均为 DEFAULT。如需将 Server 注册到指定的业务服务名或图空间,可通过 values 指定:

仅修改已有部署的配置时,保留当前 Chart 版本和 values。用 helm list 查看版本,替换下面的版本占位符:

1helm list -n hugegraph
2CHART=oci://ghcr.io/hugegraph/hugegraph-helm
3CHART_VERSION='<已安装的Chart版本>'
4helm upgrade hugegraph "$CHART" --version "$CHART_VERSION" -n hugegraph --reuse-values \
5  --set-string server.serviceId=analytics \
6  --set-string server.graphSpace=team_a \
7  --set-string server.testGraphAlias=team_a-demo

注意:非默认图空间必须在启动 Server 前先调用 PD API 创建;server.testGraphAlias 用于指定 helm test 验证的 Gremlin 图别名(区分大小写), 不会从 graphSpace 自动推导。请勿在 server.extraEnv 中重复声明服务 ID 或图空间。

3 内网镜像和存储

完整例子包含内网镜像、动态存储、七个 local PV、 GitOps 凭据、仅 API 部署以及无域名的 HTTP Ingress。

global.imageRegistry 为未指定 registry 的镜像仓库加前缀,组件指定完整 registry 地址时优先采用组件配置。 默认只需镜像仓库中的 hugegraph/pd、hugegraph/store、hugegraph/server 和 hugegraph/hubble 四个镜像,标签或 digest 按实际配置选取。 等待 PD 的 init container 复用 Store 镜像,Helm test 复用 Server 镜像。这两个镜像已包含 curl,无需额外 curl 镜像或启动时安装软件。 自定义镜像可以继续使用显式 store.waitImage 和 server.waitImage 覆盖。

启用 SeaTunnel 时还需同步其配置的 apache/seatunnel 镜像,启用 Vermeer 时使用上文固定的已发布构建。 Vermeer 的 Master、Worker 和服务令牌初始化复用同一镜像;所有已启用镜像及显式 helper 覆盖都应同步。 使用自定义 Vermeer 镜像时,还需更新 vermeer.image.digest,或在按标签选择时显式清空;非空 digest 优先于标签。

存储配置

storageClassName 为空时继承集群默认 StorageClass,"-" 表示显式不使用 StorageClass。 local PV 需要预建宿主机目录、匹配容量、nodeAffinity 和 kubernetes.io/no-provisioner StorageClass。 WaitForFirstConsumer 根据 Pod 调度约束绑定,创建资源前请查看七个卷的完整例子。 新建临时实例可以设置 persistence.enabled=false 使用 emptyDir,组件存储开关优先。 PVC 失败不会自动降级为临时存储,已经初始化的 PD/Store 切换存储模式会被拒绝。

Vermeer 的 Master 和 Worker 使用独立数据卷,单 Pod 模式也不共享 Pebble 目录。 单机模式增加 2 个卷;集群模式为 1 个 Master 卷加每 Worker 1 个卷,默认增加 4 个。 因此默认基础拓扑加 Vermeer 单机/集群分别需要 9/11 个卷,轻量 HugeGraph 预设加 Vermeer 单机需要 5 个。 七卷 local PV 示例仅覆盖基础安装;SeaTunnel checkpoint 仍使用临时本地文件。

离线安装和私库

先选择最新版本,再按该版本下载 Chart,将 .tgz 搬入内网。可以直接安装,也可以接入已有的 OCI 或 HTTP 私库。 内网安装需通过 --set global.imageRegistry=... 覆盖镜像私库, 参见 values-internal-registry.yaml。

1CHART=oci://ghcr.io/hugegraph/hugegraph-helm
2CHART_VERSION=$(helm show chart "$CHART" --devel | sed -n 's/^version: //p')
3helm pull "$CHART" --version "$CHART_VERSION"
直接安装
1# 内网环境需覆盖镜像私库(或使用 -f values-internal-registry.yaml)
2helm install hugegraph "./hugegraph-helm-${CHART_VERSION}.tgz" -n hugegraph \
3  --set global.imageRegistry=registry.example.com \
4  --create-namespace --wait --timeout 15m
OCI 私库
1helm registry login registry.example.com
2helm push "./hugegraph-helm-${CHART_VERSION}.tgz" oci://registry.example.com/charts
3helm install hugegraph oci://registry.example.com/charts/hugegraph-helm \
4  --version "$CHART_VERSION" -n hugegraph \
5  --set global.imageRegistry=registry.example.com \
6  --create-namespace --wait --timeout 15m
HTTP 私库
1# 按私库的上传方式接收同一个 .tgz,并更新 index.yaml。
2# 自建静态 HTTP 源可用 helm repo index 生成索引;helm push 只适用于 OCI。
3helm repo add hugegraph-internal https://charts.example.com
4helm repo update hugegraph-internal
5helm install hugegraph hugegraph-internal/hugegraph-helm \
6  --version "$CHART_VERSION" -n hugegraph \
7  --set global.imageRegistry=registry.example.com \
8  --create-namespace --wait --timeout 15m

私库地址请替换为实际地址。Chart 包不包含容器镜像;完整离线部署还需搬运配置引用的所有容器镜像,并覆盖镜像地址。

4 鉴权和 Secret

普通 Helm 安装自动生成、复用三份凭据,分别为 <release>-admin 的 password、<release>-auth-token 的 token_secret 以及 <release>-pd-auth 的 secret-key。PD REST 使用共享的 PD Secret,通过 HG_PD_AUTH_SECRET_KEY 注入 PD 容器, Server 等待存储和 Hubble 使用同一份凭据,不需要用户为每个 PD Pod 单独发明密码。

GitOps 使用加密的固定值,或预先创建 Secret 并配置 pd.auth.existingSecret、server.auth.admin.existingSecret 和 server.auth.token.existingSecret。existingSecret 高于内联值,chart 不管理这类外部 Secret。 管理员密码需要可打印 ASCII,不能包含空格、冒号、反斜杠;PD 密码需要可打印 ASCII,不能包含首尾空白和反斜杠;JWT key 至少 32 字节。 离线渲染器不能通过 lookup 读取在线已生成 Secret,因此不能依赖每次渲染随机生成凭据。

管理员 Secret 是初始凭据,更新 Secret 不会修改已经创建的账户密码。 先使用旧密码调用 PUT /graphspaces/DEFAULT/auth/users/admin,请求体为 {"user_password":"<新密码>"}, 再把 Secret 和源配置同步为新密码,最后重启 Server Deployment 清理所有副本的鉴权缓存。

Hubble 默认开启,当前镜像的登录仍依赖 Server 鉴权。只使用 API 可以设置 hubble.enabled=false, 如需关闭 API 鉴权,再设置 server.auth.enabled=false。未使用的凭据配置可以留在 values 中。

可选引擎的原生入口始终需要登录,easy 模式也不例外。新生成的独立管理员密码在 easy 模式下为 6 位随机字母数字,strict 模式下为 16 位。 SeaTunnel 使用 HTTP Basic,Vermeer 使用 <release>-vermeer-admin Secret 与 Admin credential 登录。 升级保留既有密码,切换模式也不会自动轮换。 Vermeer 管理密码可通过 vermeer.auth.admin.password 或 vermeer.auth.admin.existingSecret/key 配置,仅 Master 读取。 原生管理按最终 Service 类型访问:NodePort 直接通过节点 IP 和分配端口访问,ClusterIP 使用 port-forward 转发,Hubble 的服务凭据自动配置。

高级:Vermeer 部署凭据与 GitOps

GitOps 需保留稳定的管理员凭据和独立的内部服务身份。 服务签名因子通过 vermeer.auth.value 或 vermeer.auth.existingSecret/key 配置,Hubble 自动生成服务令牌; 日常 Hubble 使用和原生密码登录都不需要手工获取该令牌。 更改外部管理密码 Secret 只需重启 Master;服务签名因子轮换需重启 Master 与 Hubble,无需重启 Worker。 Worker Schema 读取默认复用部署管理员,也可通过 vermeer.hugegraphCredentials.existingSecret/key 指向现有用户的受保护用户名密码 JSON。 该用户需具备目标图的 Schema 权限,Chart 不会自动创建账户。

5 升级和验证

使用 Helm 原生值复用保留已有部署的 UI、入口、存储和凭据设置。

1helm get values hugegraph -n hugegraph --all
2# 测试环境继续跟随最新版本;生产升级请改用 --version 指定已审阅的稳定版本。
3helm upgrade hugegraph "$CHART" --devel -n hugegraph \
4  --reuse-values --wait --timeout 15m
5helm test hugegraph -n hugegraph --logs --timeout 5m

已有配置中的显式 helper 镜像也会保留。添加 --set-string store.waitImage= --set-string server.waitImage= 可清空覆盖并复用组件镜像。 要采用新的默认值,先审阅已有配置,再使用 --reset-values 和保留镜像、凭据、存储、拓扑设置的配置文件。 PD 成员、持久存储和共享凭据变更需要按生命周期说明协调处理。

基于当前 master 构建的 PD、Store 和 Server 镜像以 UID/GID 10001 运行。除非 podSecurityContext 已设置 fsGroup,Chart 会为 PD 和 Store Pod 设置 fsGroup: 10001(以及 fsGroupChangePolicy: OnRootMismatch),即使 --reuse-values 保留了旧 Release 的空值也是如此,使其能写入旧镜像(以 root 运行)创建的 PVC。

请在首次应用 fsGroup 的同一次滚动更新中,将 PD 和 Store 切换到基于此版本构建的镜像,使 kubelet 在 10001 镜像启动前修改卷的属主。不要先用仍以 root 运行的镜像(例如尚未更新到此版本的 latest)运行此 Chart:这些镜像创建的文件归 root 所有,而 OnRootMismatch 只检查卷的根目录,之后不会再修正它们。 请将 pd.image 和 store.image 固定为基于此版本构建的镜像,而不要依赖 latest。非空的 image.digest 优先于 image.tag,且 --reuse-values 会保留已有的 digest,因此按 digest 固定镜像的 Release 必须修改 digest,而不能只修改标签。

如果 Release 已在设置了 fsGroup 的情况下运行过 root 镜像,请在首次滚动更新到 10001 镜像的同时执行一次递归属主变更。请在同一条命令中设置镜像, 使递归变更作用于 10001 镜像,而不是已固定的 root 镜像。示例清空了保留下来的 digest,使标签生效;按 digest 固定镜像的 Release 应改为将 pd.image.digest 和 store.image.digest 设为此版本镜像的 digest:

1helm upgrade hugegraph "$CHART" --devel -n hugegraph --reuse-values \
2  --set pd.image.tag=<this-version> \
3  --set store.image.tag=<this-version> \
4  --set-string pd.image.digest= \
5  --set-string store.image.digest= \
6  --set pd.podSecurityContext.fsGroupChangePolicy=Always \
7  --set store.podSecurityContext.fsGroupChangePolicy=Always \
8  --wait --timeout 15m

改回原策略前,请确认每个 PD 和 Store Pod 运行的都是你设置的 10001 镜像,而不是旧的 root 镜像:

1kubectl get pods -n hugegraph \
2  -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

--reuse-values 会保留 Always,而它会在每次 Pod 启动时遍历整个卷,因此请在这些 Pod 运行后改回原策略:

1helm upgrade hugegraph "$CHART" --devel -n hugegraph --reuse-values \
2  --set pd.podSecurityContext.fsGroupChangePolicy=OnRootMismatch \
3  --set store.podSecurityContext.fsGroupChangePolicy=OnRootMismatch \
4  --wait --timeout 15m

CSI 驱动忽略 fsGroup 的卷(例如许多 NFS 驱动)和 hostPath 卷需要改为执行一次 chown -R 10001:10001。

server.storageWaitTimeoutSeconds 默认 300,通过 WAIT_STORAGE_TIMEOUT_S 传给启动脚本。 未指定的启动探针阈值按存储等待加 150 秒推导;显式探针不会被改写,但预算必须覆盖存储等待和至少 120 秒 Server 启动时间。 矛盾预算会在渲染时报出对应参数。这个等待超时不是 JVM 内存配置。

默认 helm test hook 检查连接和读取。安装或恢复后,还应重新登录 UI,并验证应用实际使用的读写查询。 调度、NetworkPolicy、滚动升级和恢复见 Kubernetes 运维。

6 部署与使用 SeaTunnel(可选引擎)

SeaTunnel 是 HugeGraph 支持的可选数据集成引擎,默认关闭。启用后,Helm 会在集群内拉起常驻的 SeaTunnel Zeta 引擎及任务 Web 前端。 官方 apache/seatunnel:3.0.0 镜像已内置 HugeGraph 连接器(Source 与 Sink),无需额外构建镜像或安装插件。

 1helm/hugegraph/
 2  examples/
 3    values-seatunnel-standalone.yaml # 单机预设(单个 Hybrid 节点,适合本地与轻量测试)
 4    values-seatunnel-cluster.yaml    # 集群预设(多个 Hybrid 节点,支持分布式并行执行)
 5    seatunnel/
 6      hugegraph-sink.conf            # 写入示例:向 HugeGraph 批量导入测试顶点
 7      hugegraph-source.conf          # 读取示例:从 HugeGraph 读取图数据并输出至日志
 8      clone/                         # 跨图整库迁移配置集
 9        copy-schema.py               # 自动化 Schema 同步脚本
10        person.conf / knows.conf     # 分标签顶点与边迁移作业配置
flowchart TB
    A["外部数据源 / 远端源图"] --> ST
    subgraph Release["同一个 Helm Release"]
        ST["SeaTunnel Zeta<br/>Hybrid 混合节点"] -->|读写| HG["HugeGraph<br/>Server + PD + Store"]
    end
    U["管理人员"] -->|Web UI / REST (HTTP Basic)| ST

6.1 选择单机或集群模式

SeaTunnel 采用 Hybrid 节点架构,单个节点同时负责作业协调调度与任务执行:

  • 单机模式(Standalone):启动 1 个常驻节点,内存占用小,适合开发测试与小规模数据处理。
  • 集群模式(Cluster):启动多个同构节点组成集群,支持分布式高可用和更大吞吐。

SeaTunnel 的副本规模与 HugeGraph 拓扑完全独立解耦。在解压包目录(或源码根目录)下,可通过组合 values 快速安装:

SeaTunnel 单机
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  -f ./hugegraph-helm/examples/values-seatunnel-standalone.yaml \
4  --wait --timeout 30m
SeaTunnel 集群
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  -f ./hugegraph-helm/examples/values-seatunnel-cluster.yaml \
4  --wait --timeout 30m
提示

若为已有 HugeGraph 集群追加 SeaTunnel,只需在现有 values 中加入 seatunnel.enabled: true 及相应模式配置,执行 helm upgrade 即可,无需重建已有图服务。SeaTunnel 镜像体积较大,建议在离线环境提前同步至私有镜像仓库。

6.2 访问 Web 控制台与鉴权

seatunnel.service.type: null 时继承全局 mode:easy 默认 NodePort,strict 默认 ClusterIP。 显式 ClusterIP 保持私有;显式 NodePort(包括 strict 模式)开放 HTTP/UI,仍需正常登录。 旧配置显式指定 ClusterIP 时,需改回 null 才会继承 easy;省略 seatunnel.service.nodePort 或设为 null 时自动分配端口。 standalone / cluster 拓扑不改变上述访问选择:

NodePort 入口(easy 模式)
1kubectl -n hugegraph get svc hugegraph-seatunnel \
2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
3kubectl get nodes -o wide
4# 访问浏览器:http://<节点 IP>:<NodePort>/#/overview
端口转发(通用)
1kubectl -n hugegraph port-forward svc/hugegraph-seatunnel 8081:8080
2# 访问本地:http://127.0.0.1:8081/#/overview

SeaTunnel 前端及 REST API 在两种模式下均需独立的 HTTP Basic 认证,与 HugeGraph 账户体系相互独立。 用户名为 admin;新生成密码在 easy 下为 6 位随机字母数字,strict 下为 16 位,升级与模式切换保留既有密码。 从 release 的 Secret 读取密码:

1kubectl -n hugegraph get secret hugegraph-seatunnel-auth \
2  -o jsonpath='{.data.password}' | base64 --decode
警告

端口 5801 为 Zeta 内部通信与 CLI 命令通道,不经过 HTTP Basic 鉴权,继续保持私有。 对外仅通过分配的 NodePort 访问需要登录的 HTTP Service,应用仍监听 8080。

6.3 运行内置示例作业

Chart 在 SeaTunnel Pod 内预置了连接 HugeGraph 的示例作业,并通过环境变量自动注入了当前 Release 内的 Server 地址、图空间及认证凭据:

  1. 准备图实例:在 Hubble 控制台或通过 REST API 创建空的测试图(默认为 DEFAULT/graph_a)。

  2. 执行导入作业:向图中的 seatunnel_demo_person 标签批量写入 10 条数据:

    1kubectl -n hugegraph exec sts/hugegraph-seatunnel -- \
    2  /opt/seatunnel/bin/seatunnel.sh --master cluster \
    3  --config /opt/seatunnel/config/hugegraph-sink.conf
  3. 执行读取验证:运行 Source 示例读取同一批顶点,并在控制台日志中查看输出:

    1kubectl -n hugegraph exec sts/hugegraph-seatunnel -- \
    2  /opt/seatunnel/bin/seatunnel.sh --master cluster \
    3  --config /opt/seatunnel/config/hugegraph-source.conf

作业执行状态可进入 Web 控制台实时查看 DAG 拓扑与指标统计。如需修改目标图或连接凭据,可在 values 的 seatunnel.env 中覆盖环境变量,或在 seatunnel.config 中挂载自定义的 .conf 配置文件。

6.4 跨图迁移与模式切换

  • 拓扑切换:单机与集群模式切换时直接修改 values 并执行 helm upgrade。切换会重置引擎进程,建议在所有批处理任务完成后再执行。
  • 跨图整库迁移:建议遵循 Schema 元数据 → 顶点数据 → 边数据 的标准顺序。可参考 examples/seatunnel/clone/ 下的自动化脚本与配置模板。迁移含有 DATE 类型字段时,务必在 Sink 配置中显式指定与源端 Server 相同的时区(如 timeZone = "UTC"),避免跨时区解析偏差。详细配置可参阅 SeaTunnel 导出与迁移文档。

1.5 - HugeGraph Kubernetes 运维

本文配合 Helm 部署使用。生命周期检查和恢复说明见 运维参考,所有参数说明见 chart 的 values.yaml。 命令假设 release 和 namespace 都是 hugegraph,覆盖名称时请替换实际工作负载名。

1 存储和内网镜像

基础安装需要七个持久卷。动态存储需要正常的 provisioner,静态 local 存储需要预建目录和绑定节点的匹配 PV。 完整例子包含七个 local PV、WaitForFirstConsumer、镜像仓库和 GitOps Secret。 WaitForFirstConsumer 的 PVC 初期 Pending 可以是正常等待;持续 Pending 应检查 PVC/Pod 事件和 PV 匹配。 PVC 已绑定但目录不存在或权限不匹配时可能挂载失败,不能把故障 PVC 静默替换成临时目录。

1kubectl -n hugegraph get pvc,pods
2kubectl -n hugegraph describe pvc <claim-name>
3kubectl -n hugegraph describe pod <pod-name>
4kubectl get pv,storageclass

出现 ImagePullBackOff 时检查 Pod 事件、仓库连通性和拉取凭据。默认只需四个组件镜像,等待 Store/Helm test 复用已包含 curl 的组件镜像。 如显式覆盖 helper 镜像,该镜像也需要同步到内网仓库。 启用 SeaTunnel 还需配置的 apache/seatunnel 镜像;启用 Vermeer 使用按 digest 固定的 hugegraph/vermeer:helm-30b67d93e7d0, Master、Worker 和令牌初始化共用它。官方发布运行记录源码与镜像 digest, 详见 Vermeer 部署指南。 自定义镜像覆盖还需同步更新 vermeer.image.digest,或显式清空以按标签选择;非空 digest 优先。 基础 local PV 示例不包含 Vermeer 卷:单机增加两个,集群增加一个 Master 卷及每 Worker 一个卷,默认增加四个。

2 端口和健康检查

PD 端口为 REST 8620、gRPC 8686、Raft 8610;Store 为 REST 8520、gRPC 8500、Raft 8510;Server HTTP 为 8080;Hubble HTTP 为 8088。 客户端 Service 隐藏 Pod 地址,NodePort 是节点上另外分配的端口,与应用监听端口不同。 PD /v1/ready 需要 Raft leader,/v1/health 只说明监听器已启动,Store 等待多数 PD peer ready 后启动。 Server 等待存储的默认上限为 300 秒,可以用 server.storageWaitTimeoutSeconds 调整。 本地模板渲染不能验证集群连通性、卷挂载或 JVM 运行容量。

保留元数据命名空间

metadataCluster: hg-test 用于声明 Server 和 Store 访问 PD 时的元数据前缀(注入至 Server 的 HG_SERVER_CLUSTER 与 Store 的 PD_CLUSTER)。 它并非 Raft 分组名,修改该值不会自动迁移历史元数据。切勿为了启用 Vermeer 将已有集群的前缀随意变更。若遇到 Server 查询正常但 Vermeer 扫描 Store 报 Schema missing 或 no such vertex label,应优先核查各组件的元数据前缀是否完全一致。

若历史自建环境使用了非默认前缀,升级前需在 Server Deployment 显式标注确认:

1kubectl -n hugegraph annotate deployment hugegraph-server \
2  hugegraph.apache.org/metadata-cluster='<已核准的历史前缀>'

并在 values 中将 metadataCluster 设为同一值。对于采用 store.updateStrategy.type=OnDelete 策略的 Store 节点,需按受控滚动升级流程逐个重建 Pod,新配置方可生效。

可选引擎运维:探针、凭据与拓扑切换
  • 端口与健康状态:SeaTunnel HTTP/UI 端口为 8080;Vermeer Master HTTP/gRPC 为 6688/6689,Worker 为 6788/6789。 原生 HTTP/UI 在 easy 下默认 NodePort,strict 下默认 ClusterIP,两者均需登录;内部 RPC、Worker HTTP 与 SeaTunnel 5801 保持私有。 service.type: null 继承模式默认值,显式 ClusterIP 保持私有,显式 NodePort 则开放需要登录的 HTTP/UI。 使用 hugegraph-seatunnel 或 hugegraph-vermeer-master Service 分配的 HTTP NodePort 与可达节点 IP 访问。 查询命令见原生入口说明;ClusterIP 可使用 port-forward。
  • 密码与会话:初次部署生成的管理密码在 easy 模式下为 6 位字符,strict 模式下为 16 位;后续升级与模式切换均自动保留既有凭据。 Vermeer 原生控制台直接在 Admin credential 填入 <release>-vermeer-admin Secret 的 password 即可登录;Hubble 内部服务凭据已自动注入。
  • 拓扑与副本切换:修改 seatunnel.mode 或 vermeer.mode 前,请确保所有计算与导入批任务已结束并卸载内存图副本。单机与集群使用独立的数据卷声明,拓扑切换不会自动迁移本地文件。
  • 完整恢复指引与进阶参数详见 Vermeer 部署指南 与 SeaTunnel 部署指南。

Helm test 检查范围

helm test 逐 Server Pod 检查图绑定(默认检查 DEFAULT-hugegraph,可通过 server.testGraphAlias 指定图别名),并要求当前可见关联索引处于 CREATED 状态。 请在索引创建/重建任务结束后执行,检查期间不要并发修改 schema。 在 HStore 上,读取尚未完成的索引可能将临时状态缓存到其他 Pod;重试不会刷新该状态。 即使任务随后成功,这些 Pod 的索引查询也可能继续失败;应在任务结束后再替换受影响的 Server Pod。 hook 不修复跨 Server 的 schema 缓存一致性。内部 150 秒重试窗口用于等待短暂选举等状态恢复, Helm 的 --timeout 不会修改这个窗口。 它按 ID 读取索引,不刷新全量索引缓存;不证明索引查询结果或完整 schema 一致性。 对已有数据,可在 Helm 升级时用 --set-file server.testGremlin=assertions.groovy 添加逐 Pod 的只读业务断言。 脚本必须用 assert 或抛异常表示结果不符,仅返回 false 不会让请求失败。 业务查询断言 给出了示例与检查边界。未配置脚本时明确显示业务断言已跳过,默认 hook 不创建 schema 或数据。 自定义脚本使用 hook 的 Server 凭据执行(开启鉴权时为 admin),不强制只读;请提供可信的只读断言。

Server API 根据 Accept-Encoding 协商响应压缩。支持 gzip 的客户端可请求 gzip 或使用 curl --compressed; identity 或未请求压缩时返回未压缩内容。需从更新后的源码重新构建 Server 镜像才能包含该行为,仅更新 chart 不会改变现有镜像。

PD REST 鉴权

PD REST 使用 HTTP Basic 鉴权,hg、store、hubble 和 vermeer 共用 PD REST Secret 密码。 Server 的 admin 不是 PD REST 账户,使用它会返回 401。默认 release/Secret 的查询示例,地址应为可达的 PD REST 地址:

1PD_SECRET=$(kubectl -n hugegraph get secret hugegraph-pd-auth \
2  -o jsonpath='{.data.secret-key}' | base64 --decode)
3curl --user "hg:${PD_SECRET}" "http://<pd-rest-address>:8620/v1/stores"

以上 HTTP 示例适用于可信内网。其他访问路径可使用 HTTPS 网关,或按需执行 kubectl -n hugegraph port-forward service/hugegraph-pd-client 8620:8620,再访问 http://127.0.0.1:8620。

使用 pd.auth.existingSecret 或自定义 pd.auth.key 时读取实际 Secret 和 key,不使用 Server 管理员密码。 变量式示例避免将密码字面值写入 shell 历史,但展开后的凭据可能短暂出现在进程参数中。 共享终端可选用 curl --user hg 提示输入密码,或权限为 600 的私有 curl 配置文件; 凭据操作说明 也包含改密请求体的处理方式。不要记录或提交凭据文件。

3 调度

默认 preferred 反亲和允许节点少于副本数时调度;values-cluster.yaml 对 PD/Store 设置 required 反亲和,因此需要至少三个可调度节点。 显式 affinity 优先于预设。local PV 节点亲和必须匹配工作负载位置约束,PV 容量声明不等于文件系统配额。 持久化 PD/Store 的 Raft 主机名和端口会记录为成员身份,不能作为普通配置随意变更。

4 分区副本

首次初始化时,Store 至少三个则默认每个分区三副本,否则一副本。 PD 会持久化分区设置,初始化后修改 chart 值不会覆盖已有元数据,应使用 PD 配置 API 并协调分区巡检。 显式 shard 数必须为奇数且不超过 Store 数,操作在线集群前先核对 拓扑约束;chart 不负责迁移已有 shard 元数据。

5 NetworkPolicy

基础服务的完整隔离在 easy 和普通集群预设下默认关闭,strict 下开启。 SeaTunnel 和 Vermeer 始终需要登录。原生策略仅在最终 Service 类型为 NodePort 时允许外部 HTTP, 内部 RPC、Worker HTTP 与 SeaTunnel 成员端口仍限制为相应 release 调用方,networkPolicy.enabled=false 也不例外。 集群网络插件必须支持策略执行,才有实际隔离效果。 生成策略允许组件间通信和 DNS,基础服务的外部客户端、Ingress 控制器需要适当的 networkPolicy.<component>.extraIngress, 外部发现地址可能还需要 extraEgress。基础服务规则的空列表合法但可能阻止外部访问,并支持 Kubernetes 原生规则,包括允许全部的 {}。 按实际来源地址或 selector 配置,并考虑 NodePort SNAT 和控制器行为。

 1networkPolicy:
 2  enabled: true
 3  server:
 4    extraIngress:
 5      - from:
 6          - ipBlock:
 7              cidr: 10.20.0.0/16
 8        ports:
 9          - protocol: TCP
10            port: 8080
11  hubble:
12    extraIngress:
13      - from:
14          - ipBlock:
15              cidr: 10.20.0.0/16
16        ports:
17          - protocol: TCP
18            port: 8088

原生引擎的 extraIngress 只接受显式内部 Pod/namespace selector,拒绝 IP block 和通配规则。 NodePort HTTP 访问已由生成的策略直接放行,无需额外的 extraIngress 规则。 上面的基础服务示例用于 Server。外部数据源可按需配置引擎 extraEgress,strict 进一步限制出站流量。

6 逐个升级 Store

集群预设使用 store.updateStrategy.type=OnDelete 便于维护时控制逐个替换。 每次只删除一个 Store Pod,下一次删除前确认上一个 Pod Ready、Store 心跳新鲜,并从 PD leader 查询每个 shard group 都有完整成员及唯一 leader。 PD 的 Up 状态本身不证明 shard 恢复完成。PDB 限制主动驱逐,不限制 StatefulSet 控制器更新。 发现缺成员或无 leader 时停止继续替换。 运维参考说明这些升级条件, 但不提供完整的逐组诊断或丢盘恢复步骤。

即使副本完整,替换单个 Store 时,Raft leader 和客户端路由收敛期间仍可能出现请求失败或超时,不保证零错误。 继续维护前同时观察应用错误和 shard 恢复状态,不要盲目重试写请求。

PD 巡检和 leader 均衡

分区巡检修复 shard 成员关系;leader 均衡是单独的手动任务,不会自动定时执行。 执行前通过鉴权的 /v1/members 查询 data.pdLeader.restUrl,并确认该 PD 的 /v1/ready 返回 isLeader: true。 GET 任务 /v1/task/patrolPartitions 和 /v1/task/balanceLeaders 会改变集群状态,应携带 PD REST 凭据请求已确认的 leader。 成员恢复和 split/move 任务完成后才能执行 leader 均衡;Store 心跳需新鲜,各组成员需完整、健康。 忙碌任务返回 body status: 1001。follower 可能返回空成功,leader 转移是异步的,HTTP 200 或转移计划不代表执行完成。 继续维护前重新检查 /v1/partitions、/v1/stores 和应用错误。 任务操作步骤 说明巡检和均衡的独立操作;维护忙碌时不要循环请求任务。

7 灾难恢复

保留原卷、claim 身份和 PD 成员关系,不通过删除 RocksDB lock 文件恢复,也不把持久化成员配置替换为全新的节点。 Store 丢盘后,新建空 PVC 并不能恢复原有数据。 local 磁盘不能在节点故障时自动迁移文件。备份应放在这些 PV 之外,并单独验证恢复;chart 不提供自动备份和自动恢复。 恢复说明列出恢复约束,不是完整的恢复操作顺序。 破坏性变更前,应结合部署版本、剩余副本或备份制定并验证恢复方案。

8 扩缩容

Server 副本可以常规变更,HPA 还需要 CPU requests。Store 扩容需要协调存储和 shard。 PD 扩缩容及 Store 缩容不能仅修改副本数,需要先更新持久化 Raft/shard 成员关系。 chart 对已初始化 StatefulSet 检查不支持的身份和成员变更,首次安装不执行升级专用查询。 按生命周期流程扩缩容,避免直接 kubectl scale 使 Hubble 的 Store metrics 配置过期。

9 集群外的 Hubble

direct 模式只需要可达的 Server URL;PD discovery 还需要集群外可达的 PD gRPC,PD 注册的 Server 地址也必须可达。 必要时用 server.advertiseUrl 注册共享 Server 地址,这会影响所有 discovery 客户端,包括集群内 Hubble。 chart 内置 Hubble 已配置内部服务发现,不需要公开 PD 入口。 HTTP 可以直接使用,TLS 终止可选。Hubble 仍是单副本,当前登录依赖 Server 鉴权。

10 Gremlin 报 Could not rebind

PD 滚动更新期间,Server 可能 Ready、能响应 REST,但 Gremlin binding 失败。 执行 helm test hugegraph -n hugegraph --logs --timeout 5m 检查每个 Server Pod 的鉴权图查询;PD 稳定后替换失败 Pod 并再次验证。 只查询 /versions 不证明图绑定成功,还应检查 Hubble 新登录和图查询。

出现 ERROR: missing required env 'HG_PD_AUTH_SECRET_KEY' 时,检查 PD Pod 的 Secret 引用和对应 key,不要把 Secret 值输出到日志。 chart 正常情况下自动注入共享 PD REST 凭据,自定义容器或 manifest 必须向 PD 和客户端提供同一值。 GitOps 先创建外部 Secret 再调谐工作负载,普通 Helm 保留自动创建的 release Secret。

2 - HugeGraph ToolChain

测试指南:如需在本地运行工具链测试,请参考 HugeGraph 工具链本地测试指南

HugeGraph Toolchain 包含 Java/Go 客户端、Loader、Hubble、Tools、Spark Connector 和 SeaTunnel Sink/Source。先按任务选择入口,再查看对应组件的配置与命令。

任务推荐入口适合场景
图可视化Hubble在 Web 界面查看和管理图
图导入Loader、SeaTunnel Sink、Spark Connector直接导入数据,或接入已有数据管道
图导出/迁移Tools、SeaTunnel Source备份、导出、跨图迁移和持续读取

DeepWiki 提供实时更新的项目文档,内容更全面准确,适合快速了解项目最新情况。

📖 https://deepwiki.com/apache/hugegraph-toolchain

源码仓库: apache/hugegraph-toolchain

2.1 - 使用 Hubble 实现图可视化:单机快速上手

用 Docker 启动 RocksDB Server 与 Hubble,从示例图开始建模、导入 CSV,并用 Gremlin、Cypher 或 Text2GQL 查询图数据。

Hubble 是 HugeGraph 的 Web 管理与图可视化界面。你可以在同一个工作台中管理图的 Schema、导入数据、执行查询, 并在图、表格和 JSON 视图之间自由切换。本文以 单机 RocksDB Server + Hubble 为例走通完整操作,无需预先部署 PD 或 Store。

如需搭配 HStore 分布式集群使用,可先了解本文的基础操作,再参考 HStore 分布式补充。 文档内容以 Toolchain 与 Server 的 master 分支(当前均以 1.8 为基线,尚未正式发布)为准;Docker latest 为动态标签,生产环境建议使用已发布的固定版本。

本文截图基于 HugeGraph Hubble 界面,中英文界面功能与操作一致。

警告

请勿将未配置防护的 Hubble 或 Server 直接暴露在公网上。生产环境请务必开启 HTTPS、容器网络隔离、 认证与授权及访问白名单。

可按需快速跳转到对应操作;首次使用建议从启动单机环境开始:

启动单机组合

直接使用主仓库提供的 docker/docker-compose.yml 即可, 无需自行编写 Compose 配置文件。该文件已内置编排了 RocksDB Server 与 Hubble,并配置好网络、健康检查及持久化数据卷; 完整部署说明见同目录的 README。

  1. 准备官方 Compose 配置。

    1git clone --branch master --single-branch --depth 1 https://github.com/apache/hugegraph.git
    2cd hugegraph/docker

    若本地已有主仓库,直接进入其 docker/ 目录即可。Compose 会自动挂载该目录下的 conf/hubble/standalone.properties, 已预设 pd.enabled=false 与 server.direct_url=http://server:8080。两项服务处于同一 Docker 网络中通信, 无需为每个图单独配置 Server 地址。请直接在 docker/ 目录下启动,以确保相对配置路径有效。

    Hubble 默认只在宿主机回环地址开放 8088(由 HUBBLE_PUBLISH_HOST 环境变量控制,默认为 127.0.0.1); Server 默认对外发布 8080。若仅供本机试用,可将 Compose 中 Server 的 ports 改为 127.0.0.1:8080:8080,避免匿名端口暴露到外部网络。

  2. 启动并检查服务。

    为本次试用指定一个独立的项目名,后续命令在同一终端中沿用这些环境变量;另起终端时请重新设置。

    1export HUGEGRAPH_VERSION=latest
    2export HUBBLE_IMAGE=hugegraph/hubble:latest
    3export HUBBLE_DEMO_PROJECT="hubble-demo-$(date +%Y%m%d-%H%M%S)"
    4docker compose ls
    5docker compose -p "$HUBBLE_DEMO_PROJECT" -f docker-compose.yml pull
    6docker compose -p "$HUBBLE_DEMO_PROJECT" -f docker-compose.yml up -d --wait
    7docker compose -p "$HUBBLE_DEMO_PROJECT" -f docker-compose.yml ps
    8curl -fsS http://127.0.0.1:8080/versions
  3. 打开 Hubble。

    服务启动完成后,在浏览器访问 http://127.0.0.1:8088。若未在 .env 中配置 HUGEGRAPH_ADMIN_PASSWORD,Server 默认允许匿名访问, Hubble 会直接进入首页。若已启用认证,请根据 Docker README 在 .env 中配置管理员密码与 JWT 密钥,并使用 Server 账号登录(Hubble 无独立用户库)。 个人中心与账号管理入口仅在开启认证且具备相应权限时展示。

latest 镜像便于快速体验最新功能,生产环境建议指定发布版本号或镜像 digest。正式发布包可前往 下载页 获取。

核实部署版本

文档截图用于定位界面元素,实际版本以部署镜像的 digest 及构建信息为准。

Compose 中的 server-data 与 hubble-data 卷分别持久化保存图数据与 Hubble 元数据;更多生产配置参见 Server 部署指南。

首页与任务入口

首页按“图概览 → 图导入 → 图查询”组织核心工作流。左侧导航栏可随时切换各功能模块; 顶部的图选择器用于切换当前操作的目标图,所有查询、Schema 操作和异步任务均作用于当前选中的图。 单机模式下仅包含默认的 DEFAULT 图空间,无需配置 PD。

栏目主要用途
图概览与图详情选择图、加载示例、查看数据规模,再进入建模或查询
Schema / 元数据配置定义属性、顶点类型、边类型及索引
GQL 图遍历编写查询,在图、表格和 JSON 中探索结果
内置图算法用参数表单探索邻居、路径和相似关系
异步任务跟踪后台查询、Schema 和索引操作
数据源管理上传文件或配置外部数据的读取方式
数据导入将源端字段映射到图模型,执行或调度导入
个人中心与账号管理查看个人资料、修改密码,按权限管理账号及空间成员
系统运维查看 Server 节点;PD 模式还提供集群概览和 Store / PD 节点

界面速览

图概览、Schema 和查询工作区如下,点击任一截图可查看原图。

认识图概览与图详情

在【图概览】中选择默认图 hugegraph。点击图卡片或详情,可查看该图的 Schema 结构与数据统计,并快速跳转到建模、数据导入或查询页面。

在图卡片的【更多操作】菜单中点击【加载人物与软件 Demo 图】。该示例会自动创建预设 Schema 并导入示例数据(不会清空已有数据)。 初次体验建议在空图上加载,避免与已有同名 Schema 冲突。后续章节均基于该示例图演示。

若需新建图,可在页面点击新建按钮,填写图名称、可选别名并选择 Schema 模板或示例数据。连接信息由 Hubble 后端统一配置, 无需重复填写 Server 主机与账号。用户自定义 Schema 模板属于 PD 模式功能,详见 分布式补充。

定义 Schema

Schema 规定了图中允许存储的属性、顶点与边类型,并决定顶点 ID 的生成策略与索引规则。 在【元数据配置】中,可以通过列表视图维护定义,或通过图关系视图直观查看顶点与边的拓扑结构。

定义建模时关注什么
属性数据类型、单值或多值,避免把数值读成文本
顶点类型属性、可空属性、ID 策略与主键
边类型起点和终点类型、属性、边的频次及排序键
顶点索引 / 边索引索引类型与字段,匹配实际过滤和范围查询

在人物与软件示例中,person 以 name 为主键生成 ID,age 与 city 允许为空; software 采用自定义数值 ID;边类型 created 连接人物与软件。模型定义与 Loader 示例 保持一致。

自主建模时,建议遵循 属性 → 顶点类型 → 边类型 → 索引 的顺序依次创建。 删除类型或创建/重建索引操作通常会提交为后台异步任务,操作提交后可在【异步任务】中查看最终执行结果。

在 GQL 工作台查询人物关系

进入【GQL 图遍历】,确认当前图为 hugegraph。工作台将查询编辑器与图展示区集成在一起, 支持即时执行与异步执行、常用语句收藏,并可随时从执行历史中重载语句。先在 Gremlin 编辑器中查询人物属性。

1g.V().hasLabel('person').valueMap()

这条查询适合在表格或 JSON 视图核对属性。也可以查询人物与软件的关系。

1g.V().hasLabel('person').outE('created').inV().path()

图结果支持 2D / 3D 展示。点击顶点或边查看 ID、类型和属性,双击顶点展开邻居; 布局、样式和筛选工具帮助突出重点,导出功能便于分享结果。【新增】用于创建元素,有权限时也可以编辑已有数据。 调整布局、颜色或显示范围仅影响前端画布;通过界面新增、编辑元素或执行 Gremlin 写入语句才会真正修改 Server 中的图数据。

快捷键 Ctrl / Command + Enter 可快速执行查询。普通即时执行适合小规模交互探索;大数据量或耗时查询建议提交为后台异步任务。 Cypher 查询仅在 Server 后端支持时提供。快捷键会作用于当前获得焦点的输入框(在自然语言框中生成查询,在语句框中执行已有语句)。

Text2GQL 自然语言查询

在【自然语言】输入框中用自然语言描述查询需求,Text2GQL 会结合当前图的 Schema 自动生成只读 Gremlin 或 Cypher 语句并执行查询。 生成的语句支持二次编辑(执行前同样会进行只读安全校验)。切换至【异步】模式时,生成的查询与手写查询均可提交为后台异步任务。 输入框会自动恢复当前图最近一次的查询输入(不会自动触发执行),执行记录中也会完整保留原始自然语言问题。

配图中的模型尚未配置,图结果来自手写 Gremlin;自然语言生成功能需要先连接可用模型。

模型来源配置与保存方式
使用内置模型在【系统与运维 → 模型设置】统一配置,Key 加密存入 H2,不回传浏览器
使用临时模型在查询页填写 API 类别、Base URL、模型名称和临时 API Key;Key 只保留在前端内存中,刷新后清除

使用 OpenAI、DeepSeek、GLM 等模型时选择【OpenAI 兼容接口】;使用本地运行的 Ollama 时选择【Ollama(本地)】(无认证时 Key 可留空)。 Base URL 必须能被 Hubble 后端服务正常访问(若 Hubble 运行在容器中,localhost 指向容器本身而非宿主机)。公网端点必须使用 HTTPS,HTTP 仅允许用于 本地回环或私网模型;在【模型设置】中修改 Base URL 时,必须重新填写 Key 或清空已保存的 Key。 全局内置模型由具备模型设置管理权限的管理员统一配置;未开启 Server 认证时,任何访问者均可配置。

在模型设置页面右上角打开 Text2GQL Prompt,可分别定制 Gremlin 与 Cypher 的生成规则及 Few-shot 示例。 点击【应用】后需保存模型设置,模板将持久化存入 H2 数据库供内置模型与临时模型共享,生成时会自动附加当前图的 Schema。

API Key 存储与隐私说明

备份 Hubble H2 数据库时,请一并备份主密钥文件(默认路径 data/text2gql-master.key),该文件丢失将导致无法解密已保存的 Key。 生成查询时仅向模型接口发送用户问题、当前 Schema 及纠错提示,绝不会发送图数据查询结果。 浏览器可选择记住常用的 Base URL 与模型名称,但临时 API Key 仅保留在前端内存中,刷新页面即自动清除。

页脚分别显示模型生成耗时与查询请求耗时;异步提交耗时仅代表任务入队耗时,不代表后台任务实际运行时间。

使用内置图算法

不想从头编写遍历语句时,可以进入【内置图算法】,搜索算法并填写参数。 邻居探索用于回答“这个点附近有什么”,路径算法用于寻找两个点的连接,相似度和排序算法用于比较或筛选顶点。 从一个已知顶点 ID 开始,先限定方向、边类型、深度与返回规模,再观察结果,会比直接运行大范围计算更容易理解。

算法表单提供参数说明及文档入口;常用参数可以在页面间往返时恢复。 运行结果按算法显示为图或相应的结果面板;需要理解具体定义和参数时,使用算法标题旁的说明与文档链接。 表单聚焦时也可用 Ctrl / Command + Enter 运行当前算法。

OLAP 批量算法需要 Computer 或 Vermeer 等外部计算环境。本例的两个容器用于在线图操作,不包含这些计算服务。

例如选择 K-neighbor(GET),设置 source=1:marko、max_depth=1、limit=20, 参数校验通过后点击卡片右侧运行按钮,或在参数表单内使用快捷键,即可观察一跳邻居。

内置邻居算法的参数与图结果

查看异步任务的最终结果

【异步任务】集中显示当前图的后台任务,包括异步查询及部分 Schema、索引操作。 可以按任务类型和状态筛选,查看任务 ID、创建时间与执行状态;成功查询可打开结果,失败任务可展开错误信息。 已结束的任务可按界面提供的操作删除记录,任务列表与导入任务的执行历史是两个不同入口。

例如把 g.V().count() 以异步方式提交后,先在列表确认成功,再查看返回的数量。 “提交成功”只表示请求被接受,不表示计算或索引已完成。排查失败时,结合任务错误和 Server 日志定位原因。

准备数据源

数据源负责“从哪里读、怎样解析”,可以被导入任务引用。Hubble 支持 FILE、HDFS、JDBC 和 Kafka; 不同来源需要对应的路径、连接或订阅配置。首次体验可选择 FILE。上传文件后,配置格式、分隔符、编码和表头, 检查读取的列名,再进入映射。上传限制和允许的扩展名由 Hubble 配置决定。

为人物示例保存一个 UTF-8 文件 people.csv。

1name,age,city
2docs_alice,28,Beijing
3docs_bob,32,Shanghai

创建 FILE 数据源并上传它,选择 CSV(逗号分隔、默认 UTF-8),列名为 name,age,city。 表头、分隔符和编码属于数据源配置,不在后面的映射步骤设置;源字段应与文件内容一致。

映射字段并导入数据

【数据导入】把数据源中的行转换为顶点和边。任务创建采用四段配置,先明确目标,再选择字段和映射,最后决定执行时机。 沿用上面的数据源,在 DEFAULT / hugegraph 中创建人物导入任务。

  1. 基础信息 选择目标图与刚创建的数据源,填写任务名。
  2. 源端字段 选择 name、age、city,移到已选字段列表。
  3. 映射字段 添加 person 顶点映射,用【自动匹配】关联同名属性后核对类型。
  4. 调度信息 选择执行一次,确认后提交任务。

person 使用 PRIMARY_KEY,不设置独立 ID 列。自定义 ID 策略需要指定 ID 列; AUTOMATIC 由 Server 生成 ID,PRIMARY_KEY 根据映射的主键属性生成 ID。边映射还需指定起点、终点字段并匹配对应顶点的 ID 规则。

任务列表用于管理配置和执行入口,详情中的执行历史用于查看每次实例的状态、导入量与错误。 Hubble 还提供周期调度和 Kafka 实时执行,调度方式需与数据源类型匹配。 完成后返回 GQL 工作台查询新导入的数据。

1g.V().hasLabel('person').has('name', within('docs_alice', 'docs_bob')).valueMap()

结果应包含两条新人物记录。导入量统计不应直接当作新增顶点数;重跑可能更新已有元素,表头处理也会影响读取统计。 失败时先检查源字段、数值类型、可空属性及目标 Schema。Hubble 导入适合小规模体验, 大批量正式导入请使用 HugeGraph Loader。

个人中心与账号权限

Hubble 使用 Server 的认证和账号,没有独立用户库。匿名访问时不显示【个人中心】与【账号管理】; 开启认证后,个人中心展示当前账号资料与权限信息,可修改自己的密码。昵称等资料编辑依赖 Server 对个人资料接口的支持。 修改密码后会退出当前会话,需要重新登录。

单机账号管理

单机模式由管理员管理账号,可创建、查看、编辑或删除账号,并支持批量创建。 通过 Hubble 新建的普通单机账号会获得覆盖所有图的读、写、删除和执行权限,不能把它当作只读账号或单图隔离账号。 需要更细的资源权限时,应按 Server 认证与授权配置,而不是依赖空间预设。

PD 模式的空间权限

连接支持默认角色接口的 Server 后,账号与空间访问可以分别管理。管理员管理全局账号, 空间管理员只管理已授权空间的成员;普通成员不会获得账号管理或运维入口。 以下四种预设属于 PD 模式,不表示旧版本或单机 Server 都提供同样的权限编辑能力。

预设范围与用途
SUPER_ADMIN全局管理账号、图空间和运维;可授予或撤销超级管理员
GS_ADMIN管理已授权图空间及其成员,不授予其他空间或全局超级管理员权限
GS_READ_WRITE在已授权空间执行图数据读写操作,不管理全局账号
GS_READ_ONLY在已授权空间读取图数据,不进行写入

同一账号在不同空间可以有不同权限。成员管理先选择空间,再添加已有账号或调整权限; 把已有自定义权限替换为预设前,先核对需要保留的授权,避免把复杂权限误认为单一预设。 权限变更后刷新权限上下文或重新登录,确认菜单和目标空间已更新;最终请求仍由 Server 校验。 旧 Server 未提供相应接口时,页面按能力隐藏或禁用操作,不应只凭按钮是否可见推断资源权限。 更完整的空间管理见 分布式补充。

认证模式下的账号列表(单机模式示例)

检查单机 Server

单机模式的【系统运维】提供【节点信息】,只显示 Server,不显示 PD / Store 节点或集群概览。 节点列表可搜索、筛选健康状态并进入详情;详情用于查看可用的版本、系统、JVM、Server 后端等指标。 指标缺失或标记过期时,应结合采集状态与最近成功时间判断,不能把空值当作零或健康。

匿名模式可以查看运维信息;开启认证后,运维入口仅对有运维权限的管理员显示。 此处用于观测和排查,不是启动、停止或扩缩容控制台。PD 模式的集群概览与节点层级见分布式补充。

快捷键与画布操作

顶部的快捷键帮助入口随时可查看按键说明。以下快捷键有不同的作用范围,输入框中不会触发全局 ? 帮助。

操作按键或动作生效位置
打开 / 关闭快捷键说明?输入框和编辑器之外
执行查询Ctrl 加 Enter / Command 加 Enter查询编辑器
运行当前算法Ctrl 加 Enter / Command 加 Enter算法参数表单
切换图全屏F先点击聚焦图画布;不是全局按键
查看元素详情单击顶点或边图结果
展开相邻关系双击顶点图结果

排查连接与结果问题

现象先检查
Hubble 页面打不开检查容器状态及 docker compose -p "$HUBBLE_DEMO_PROJECT" -f docker-compose.yml logs hubble
页面打开但无法访问图Server 是否健康,server.direct_url 是否能从 Hubble 容器访问,两个容器是否在同一网络
出现登录页或没有写操作入口Server 的认证模式和当前账号权限;Hubble 不单独开启认证
查询没有预期数据顶部当前图、示例是否加载成功、标签和属性是否一致;区分画布展示与 Server 数据
没有集群概览本例没有 PD;集群功能见分布式补充

查询显示规模受配置影响。gremlin.suffix_limit 默认 250,用于对适用的 Gremlin 查询追加 .limit(N), 不是所有查询的硬上限;gremlin.vertex_degree_limit(100)与 gremlin.edges_total_limit(500)限制展开规模。 FILE 上传默认允许 csv,txt,单文件 1 GB、总量 10 GB;需要覆盖时修改 upload_file.* 配置。

停止试用环境或从源码构建

清理测试环境时,在 docker/ 目录下执行以下命令:

1docker compose -p "${HUBBLE_DEMO_PROJECT:?}" -f docker-compose.yml down --volumes

这会删除该项目的容器、网络、命名卷与匿名卷,示例图和 Hubble 导入任务也会丢失。 若想保留数据,下线时省略 --volumes,以后用同一项目名启动。

从当前 master 构建时,需要 JDK 17、Maven 3.9+、Python 3.9+、稳定版 Node.js 24(至少 24.22.0), 并通过 Corepack 使用仓库锁定的 pnpm 12.14.0。Maven 不再自动安装 Node/Yarn。

  1. 按 Java 17 构建说明 编译并安装 Server SDK 到独立 Maven 仓库。

  2. 按 Hubble 源码构建步骤 安装 Python 依赖,再使用同一 Maven 仓库构建 Client、Loader 和 Hubble(跳过测试)。

  3. 进入构建生成的 hugegraph-hubble/apache-hugegraph-hubble-* 目录,配置 conf/hugegraph-hubble.properties 中的 Server 连接信息后启动:

    1bin/start-hubble.sh -d

当前 master 使用新的 H2 元数据库。升级时保留旧 Hubble 包及其数据,新版使用独立的数据目录;旧元数据不支持自动迁移,不能直接复用。

打包配置默认绑定本机 localhost:8088。bin/stop-hubble.sh 会先请求正常停机,超时后才强制终止。 需要开发与测试说明时,参考 Toolchain 本地测试指南。

2.2 - 图可视化

Hubble 为 HugeGraph 提供图数据、Schema、查询和导入的 Web 界面。先从不依赖 PD 的单机组合入手, 再按需要了解分布式集群的差异。

2.2.1 - 使用 Hubble 管理 HStore 分布式集群

连接 HStore 与 PD,理解 Hubble 的图空间、Schema 模板、集群拓扑和节点指标。

本篇重点介绍 HStore + PD 分布式部署与单机 RocksDB 的核心差异。图建模、数据导入和图遍历等通用操作请参考 Hubble 基础与单机指南。 内容以 Toolchain、Server、PD 与 Store 的 master 分支(当前版本均为 1.8.0)为准。

主仓库的 docker/docker-compose-hstore.yml 已提供完整的 PD、Store、Server 与 Hubble 服务编排。请直接参考同目录 Docker README 配置 .env 并生成 Hubble 本地配置文件,然后在 docker/ 目录下启动,无需自行维护部署文件。 下文重点说明连接与运维配置要点,部署前请确保满足 README 中的 PD 凭据与前置依赖要求。 Docker latest 为动态标签,配图用于定位界面,实际版本以部署镜像的 digest 及构建信息为准。 不同版本可提供的指标和权限接口有所区别。

本文截图基于 HugeGraph Hubble 界面,中英文界面功能与操作一致。

连接分布式集群

Hubble 仍通过 Server 的图 API 管理数据。区别在于,分布式模式通过 PD 发现 Server, 同时从 PD 和 Store 获取集群信息;Hubble 不直接读写 Store 中的图数据。

flowchart LR
    H[Hubble] -->|图 API| S[Server]
    S -->|读写图数据| T[Store]
    H -.->|服务发现与集群信息| P[PD]
    H -.->|节点指标| T
  1. 生成 Hubble 配置。 按 Docker README 在主仓库的 docker/ 目录准备 .env。

    1set -a
    2. ./.env
    3set +a
    4./set-hubble-pd-password.sh hstore

    脚本会读取 .env 中的 HG_PD_AUTH_SECRET_KEY,将其值作为 operations.pd.password 写入生成文件 docker/conf/hubble/hstore.local.properties。 若需调整连接地址或运维参数,直接编辑该文件即可(请勿覆盖 Git 跟踪的 .example 模板文件),并确保 operations.pd.password 与 PD 所用密钥一致。Compose 会将该文件只读挂载到容器内部,无需进入容器修改。 该生成文件与 .env 均属于敏感配置,请勿提交到版本库;重新运行脚本会覆盖该文件,届时需重新补齐自定义参数。

  2. 启动服务。 在同一 docker/ 目录启动组合,确认 Server 已注册、Store 已就绪。

    1docker compose -f docker-compose-hstore.yml up -d --wait

若分别部署服务,参照 PD 部署指南 和 HStore 部署指南;源码或二进制包启动的 Hubble 则编辑其 conf/hugegraph-hubble.properties。以下连接项与官方最小拓扑一致,其他部署请使用 Hubble 后端实际可达的地址。

1pd.enabled=true
2cluster=hg
3pd.peers=pd:8686
4pd.server=pd:8620
配置用途随包配置值
pd.enabled显式启用 PD 模式;此时不使用 server.direct_url。false
cluster用于 Server 服务发现的集群名称,应与注册信息一致。hg
pd.peersPD gRPC 地址;多个地址用逗号分隔。127.0.0.1:8686
pd.server集群运维使用的 PD REST 地址,不是 gRPC peer 列表。127.0.0.1:8620

请区分两个端口。8686 为 gRPC 端口,8620 为 REST 端口,切勿混用;跨容器通信时请使用容器服务名或网络可达 IP,避免使用 127.0.0.1。 发行包默认配置中显式设为 pd.enabled=false;若未配置该项,代码默认值为 true,因此单机与分布式部署均建议显式声明该配置。 修改配置后,源码或二进制部署需重启 Hubble 服务;Docker Compose 部署则在 docker/ 目录下重新创建 Hubble 容器以重新加载挂载配置 (沿用启动时的项目名及所有 -f 参数)。

1docker compose -f docker-compose-hstore.yml up -d --force-recreate hubble

在 Hubble 界面中无需为每个图单独配置 Server 主机与端口。

用图空间组织图与权限

GraphSpace(图空间)将图、Schema 模板和访问权限组织在同一个范围内。例如,分别为业务团队创建 sales 与 research, 让各团队只看到并操作自己的图。进入图空间后,图的建模、导入和查询仍沿用基础指南的流程。

创建与调整图空间

开启 Server 认证时,创建、编辑和删除图空间要求超级管理员权限。创建时先填写全局唯一的 GraphSpace 名称、 可选的显示别名及最大图数;例如用 research 作 API 标识,用“研究图谱”作显示名。GraphSpace 名称创建后不可修改, 别名和描述可随后调整,别名不参与 URL 或权限匹配。图空间管理员从已有账号中选择。

“高级部署与资源限制”包含图查询/写入服务、异步计算任务的 CPU 与内存上限,以及存储容量限制。 这些部署配额不会显示实时资源用量,也不会自动扩容现有容器。

高级部署的默认值

默认最大图数为 100;图服务与计算任务分别为 64 核、128 GB,存储上限为 1000000 GB。 普通容器试用可保留默认值。Kubernetes 命名空间、Operator 和算法镜像仅在对应场景中填写。

选择图空间后,再进入其中的图。切换空间时应重新确认当前图,尤其是不同空间中存在同名图时。 列表只显示账号可访问的空间;看不到预期空间时,先检查成员权限,不要反复新建图。

图空间创建表单与高级资源限制入口

复用 Schema 模板

用户 Schema 模板仅适用于 PD 模式,按图空间持久化保存 Groovy Schema。 当一组业务图需要同样的顶点类型、边类型和索引时,可以先保存模板,再在创建图时选择它,减少重复建模。 例如 research 中的用户模板用于该空间后续创建的图;切换到另一个空间后,应重新选择该空间的模板。

主篇的内置示例模板用于快速体验预设模型。用户模板用于保存自己的模型并长期复用。 模板本身不等于导入数据;是否加载示例数据是创建图时的另一个选择。 开启 Server 认证时,创建用户模板需要所在空间的写权限,更新或删除还要求模板所有者或相应管理权限。 匿名模式不进行按用户的权限与模板所有者检查。 单机模式不提供用户模板管理。

给用户分配图空间权限

账号创建、登录和个人资料管理见基础指南; 分布式模式额外提供“管理 GraphSpace 成员”,在已有账号与指定空间之间分配权限。 支持权限预设的 Server 提供以下常用选择。

预设适用对象作用范围
GraphSpace 只读查看、查询图数据的使用者所选空间。
GraphSpace 读写建模、导入和维护图数据的使用者所选空间。
GraphSpace 管理员管理该空间的成员与图资源的负责人所选空间,不因此获得创建/编辑图空间或集群运维权限。
超级管理员管理账号、图空间及集群的运维人员全局,应按实际职责分配。

同一账号可在不同空间拥有不同权限,例如对 research 读写、对 sales 只读。 账号与空间成员分开管理,移除成员不会删除全局账号。创建账号后可以立即继续分配空间权限;调整已有成员时,确认当前空间及预设,保留其他空间仍需要的权限。 仅启用 pd.enabled 不会授予权限,旧 Server 的自定义角色也不能直接当作这些预设处理。 认证配置见 Server 认证与授权。

GraphSpace 成员与权限预设

从集群概览定位异常

集群概览用一张拓扑展示 Server → PD → Store,可切换节点列表按类型、状态或名称筛选。 概览中的 PD Leader、在线 Store 数、图数、分区数、副本数和数据量,帮助判断当前连接的规模及哪些节点需要关注。 分区和副本描述数据分布;数据量是采集到的用量,不是图空间配置的存储上限。

先看集群和来源状态,再进入异常节点。UP 表示本次采集的来源正常;DEGRADED 表示集群或部分来源异常; DOWN 表示相应探测未成功。拓扑可用而指标部分缺失时,仍可能正常查询图。 页面会区分不支持、不可用、数据过期和采集失败,并显示采集时间;空值不是零,历史值也不等于当前状态。

节点详情读什么

节点主要关注信息如何使用
Server节点可用性、JVM/CPU/内存及后端指标判断查询与写入入口是否可达,并检查资源压力。
PDLeader/Follower 角色、状态及上游可提供的运行指标确认元数据与调度入口;Leader 信息缺失时不推断角色。
Store分区数、Leader 分区数、系统/磁盘指标,以及 Raft 组数和启用组数检查存储节点及副本服务,结合其他节点比较分布。

PD Leader 与 Store 的 Leader 分区分别负责不同的工作。前者协调集群元数据,后者负责相应数据分区的 Raft 组。 Hubble 展示上游提供的观测值,不代替完整的 Raft 副本一致性检查;各版本可用的指标不同。

开启 Server 认证时,集群运维读取要求超级管理员(ADMIN 级别),空间管理员和普通成员不会因此获得集群读取权限。 部署时使用容器隔离、可信 HTTPS 入口、Server 认证与网络白名单,避免直接公开 Hubble 和组件端口。

配置运维访问

PD/Store 的运维凭据由 Hubble 后端使用,与浏览器登录 Server 的账号分开。 Compose 部署修改上文生成的宿主机 docker/conf/hubble/hstore.local.properties;其他部署修改 Hubble 包内配置文件。 其中 PD 密码由脚本生成并与 .env 中的密钥保持一致,Store 启用认证时再配置对应服务账号。不要把密码写进文档、截图或提交的配置。

配置随包默认值设置方式
operations.pd.username / operations.pd.password用户名 hubble,密码为空与 PD 运维 REST 认证匹配。
operations.store.username / operations.store.password用户名 hubble,密码为空上游 Store REST 启用认证时配置对应服务账号。
operations.store.allowed_targets[http://127.0.0.1:8520,http://[::1]:8520]列出信任的 Store 指标来源。

例如容器中的 Store 上报 store:8520,将白名单配置为以下内容。

1operations.store.allowed_targets=[http://store:8520]

多节点集群中需列出所有允许访问的目标地址。每项必须是包含显式端口的 http 或 https 源地址(Origin),不可包含路径、凭据或通配符, 且需与 PD 返回的 Store 指标目标完全一致。仅在白名单中添加地址不会自动建立节点发现。

若集群拓扑可见但节点指标不完整,请依次检查 Hubble 后端到 PD REST 的网络连通性与认证凭据、PD 返回的 Store REST 与指标地址, 以及目标地址是否已加入上述白名单。概览中的部分可用状态仅表示特定来源指标采集受阻,并不代表图 API 服务不可用。

2.3 - HugeGraph-Loader 快速上手

本文以 Toolchain master 分支(以 1.8 为基线,尚未正式发布)为准。发布版和 Docker latest 可能存在部分差异,使用未发布功能前请先核对版本。

快速上手:本地文件导入

下面通过一个最简示例体验 Loader 的基本导入流程:导入两个人和一条关系,并在 Hubble 中查询验证。 请先安装 Loader 并启动 HugeGraph Server。 以下命令均在 Loader 安装目录下执行,连接本地默认图 hugegraph。若 Server 已启用鉴权,在命令中追加 --username 与 --password(或 --token)。

  1. 创建数据文件

    两份 CSV 均不含表头,列名由下一步的映射文件指定。

    1mkdir -p demo-loader
    2cat > demo-loader/people.csv <<'EOF'
    3docs-smoke-alice,29
    4docs-smoke-bob,31
    5EOF
    6cat > demo-loader/knows.csv <<'EOF'
    7docs-smoke-alice,docs-smoke-bob
    8EOF
  2. 创建 Schema 和映射文件

    本例使用独立的 docs_* 名称,避免与内置的 person 数据冲突。 映射文件中的路径相对于运行 Loader 时的工作目录。

     1cat > demo-loader/schema.groovy <<'EOF'
     2schema.propertyKey("docs_name").asText().ifNotExist().create()
     3schema.propertyKey("docs_age").asInt().ifNotExist().create()
     4schema.vertexLabel("docs_smoke_person").properties("docs_name", "docs_age")
     5      .primaryKeys("docs_name").ifNotExist().create()
     6schema.edgeLabel("docs_smoke_knows").sourceLabel("docs_smoke_person")
     7      .targetLabel("docs_smoke_person").ifNotExist().create()
     8EOF
     9cat > demo-loader/struct.json <<'EOF'
    10{
    11  "version": "2.0",
    12  "structs": [
    13    {
    14      "id": "people",
    15      "input": {
    16        "type": "FILE",
    17        "path": "demo-loader/people.csv",
    18        "format": "CSV",
    19        "header": ["docs_name", "docs_age"]
    20      },
    21      "vertices": [{"label": "docs_smoke_person"}]
    22    },
    23    {
    24      "id": "knows",
    25      "input": {
    26        "type": "FILE",
    27        "path": "demo-loader/knows.csv",
    28        "format": "CSV",
    29        "header": ["source_name", "target_name"]
    30      },
    31      "edges": [{
    32        "label": "docs_smoke_knows",
    33        "source": ["source_name"],
    34        "target": ["target_name"],
    35        "field_mapping": {"source_name": "docs_name", "target_name": "docs_name"}
    36      }]
    37    }
    38  ]
    39}
    40EOF
  3. 执行导入

    保持在同一工作目录。Server 运行在其他地址时,修改主机和端口。

    1bin/hugegraph-loader.sh \
    2  --graphspace DEFAULT --graph hugegraph \
    3  --file demo-loader/struct.json --schema demo-loader/schema.groovy \
    4  --host 127.0.0.1 --port 8080

    首次成功导入后,统计应显示两个顶点、一条边。检查汇总中的成功数和失败数。

  4. 在 Hubble 中查询结果

    将 Hubble 连接到同一个 Server 和图,在 Gremlin 工作台分别执行以下查询。

    1g.V().hasLabel('docs_smoke_person').valueMap('docs_name', 'docs_age')
    2g.V().has('docs_smoke_person', 'docs_name', 'docs-smoke-alice')
    3 .out('docs_smoke_knows').values('docs_name')

    第一条查询返回 Alice 的年龄 29、Bob 的年龄 31,第二条返回 docs-smoke-bob。

导入其他数据源时,继续阅读映射文件参考。 内置完整示例还包含软件顶点和边属性。

1 HugeGraph-Loader 概述

HugeGraph-Loader 是 HugeGraph 的数据导入组件,能够将多种数据源的数据转化为图的顶点和边并批量导入到图数据库中。

目前支持的数据源包括:

  • 本地磁盘文件或目录,支持 TEXT、CSV 和 JSON 格式的文件,支持压缩文件
  • HDFS 文件或目录,支持压缩文件
  • 主流关系型数据库,如 MySQL、PostgreSQL、Oracle、SQL Server
  • Kafka topic
  • 已有的 HugeGraph 图,用于把数据从一个图复制到另一个图

本地磁盘文件和 HDFS 文件支持断点续传。

注意:使用 HugeGraph-Loader 需要依赖 HugeGraph Server 服务,下载和启动 Server 请参考 HugeGraph-Server 快速上手

测试指南:如需在本地运行 Loader 测试,请参考 工具链本地测试指南

并发导入保护:Toolchain master 分支的 Loader 已支持针对同一 Server 实例的 LOADING owner 保护。当配套 Server 的 GET .../mode/owners 返回 protocol: 1 时会自动生效;若 Server 无此接口,则保持原有导入行为。

2 获取 HugeGraph-Loader

可以通过以下三种方式获取 HugeGraph-Loader:

  • 使用 Docker 镜像 (便于测试)
  • 下载已编译的压缩包
  • 克隆源码编译安装

2.1 使用 Docker 镜像 (便于测试)

我们可以使用 docker run -itd --name loader hugegraph/loader:latest 部署 loader 服务。对于需要加载的数据,则可以通过挂载 -v /path/to/data/file:/loader/file 或者 docker cp 的方式将文件复制到 loader 容器内部。

或者使用 docker-compose 启动 loader, 启动命令为 docker-compose up -d, 样例的 docker-compose.yml 如下所示:

以下组合用于本地匿名试用,Server API 只发布到本机。

 1version: '3'
 2
 3services:
 4  server:
 5    image: hugegraph/hugegraph:latest
 6    container_name: server
 7    ports:
 8      - 127.0.0.1:8080:8080
 9
10  loader:
11    image: hugegraph/loader:latest
12    container_name: loader
13    # mount your own data here
14    # volumes:
15      # - /path/to/data/file:/loader/file

具体的数据导入流程可以参考 4.5 使用 docker 导入

注意:

  1. hugegraph-loader 的 docker 镜像是一个便捷版本,用于快速启动 loader,并不是官方发布物料包方式。你可以从 ASF Release Distribution Policy 中得到更多细节。

  2. 生产环境应固定已发布的版本标签或镜像 digest。latest 是可变标签,不能据此判断其与 master 一致。

2.2 下载已编译的压缩包

从 下载页面 选择已发布的 Toolchain 压缩包并解压。 发布包不一定包含 master 的全部功能;需要本文对应实现时,使用下一节的源码构建方式。

2.3 克隆源码编译安装

从 master 分支编译 Loader 需要 Java 17、Maven 3.6.3+ 与 Python 3.9+。直接克隆仓库并编译:

1git clone --branch master --single-branch https://github.com/apache/hugegraph-toolchain.git
2cd hugegraph-toolchain
3mvn package -pl hugegraph-client,hugegraph-loader -am -DskipTests -ntp
4cd hugegraph-loader/apache-hugegraph-loader-*

如需搭配开发阶段的 Server master SDK 编译,可参阅 Java 17 迁移指引。

如需读取 Oracle 数据,按所用 Oracle/JDK 版本准备兼容的 JDBC 驱动 JAR,并放入解压后 Loader 的 lib/ 目录。 启动脚本会加载该目录中的 JAR;仅将驱动安装到 Maven 本地仓库并不会让运行中的 Loader 找到它。

3 使用流程

导入数据前先准备图模型、数据文件和映射文件,再运行 Loader。

  • 编写图模型
  • 准备数据文件
  • 编写输入源映射文件
  • 执行命令导入

3.1 编写图模型

先确定数据对应的顶点类型、边类型和属性,再编写 Schema。

以下示例包含 person 和 software 两类顶点,以及 knows 和 created 两类边。 人有姓名、年龄和城市,软件有名称和价格,两类边都记录日期。

由“认识”和“创建”边连接人物与软件顶点的示例图

示例图模型

将 Schema 定义保存到 schema.groovy。

 1// 创建一些属性
 2schema.propertyKey("name").asText().ifNotExist().create();
 3schema.propertyKey("age").asInt().ifNotExist().create();
 4schema.propertyKey("city").asText().ifNotExist().create();
 5schema.propertyKey("date").asText().ifNotExist().create();
 6schema.propertyKey("price").asDouble().ifNotExist().create();
 7
 8// 创建 person 顶点类型,其拥有三个属性:name, age, city,主键是 name
 9schema.vertexLabel("person").properties("name", "age", "city").primaryKeys("name").ifNotExist().create();
10// 创建 software 顶点类型,其拥有两个属性:name, price,主键是 name
11schema.vertexLabel("software").properties("name", "price").primaryKeys("name").ifNotExist().create();
12
13// 创建 knows 边类型,这类边是从 person 指向 person 的
14schema.edgeLabel("knows").sourceLabel("person").targetLabel("person").properties("date").ifNotExist().create();
15// 创建 created 边类型,这类边是从 person 指向 software 的
16schema.edgeLabel("created").sourceLabel("person").targetLabel("software").ifNotExist().create();

关于 schema 的详细说明请参考 HugeGraph Java Client 中对应部分。

3.2 准备数据

目前 HugeGraph-Loader 支持的数据源包括:

  • 本地磁盘文件或目录
  • HDFS 文件或目录
  • 部分关系型数据库
  • Kafka topic
  • 已有的 HugeGraph 图
3.2.1 数据源结构
3.2.1.1 本地磁盘文件或目录

用户可以指定本地磁盘文件作为数据源,如果数据分散在多个文件中,也支持以某个目录作为数据源,但暂时不支持以多个目录作为数据源。

比如:我的数据分散在多个文件中,part-0、part-1 … part-n,要想执行导入,必须保证它们是放在一个目录下的。然后在 loader 的映射文件中,将path指定为该目录即可。

支持的文件格式包括:

  • TEXT
  • CSV
  • JSON

TEXT 是自定义分隔符的文本文件,第一行通常是标题,记录了每一列的名称,也允许没有标题行(在映射文件中指定)。其余的每行代表一条记录,会被转化为一个顶点/边;行的每一列对应一个字段,会被转化为顶点/边的 id、label 或属性;

示例如下:

1id|name|lang|price|ISBN
21|lop|java|328|ISBN978-7-107-18618-5
32|ripple|java|199|ISBN978-7-100-13678-5

CSV 是分隔符为逗号,的 TEXT 文件,当列值本身包含逗号时,该列值需要用双引号包起来,如:

1marko,29,Beijing
2"li,nary",26,"Wu,han"

JSON 文件要求每一行都是一个 JSON 串,且每行的格式需保持一致。

1{"source_name": "marko", "target_name": "vadas", "date": "20160110", "weight": 0.5}
2{"source_name": "marko", "target_name": "josh", "date": "20130220", "weight": 1.0}
3.2.1.2 HDFS 文件或目录

用户也可以指定 HDFS 文件或目录作为数据源,上面关于本地磁盘文件或目录的要求全部适用于这里。除此之外,鉴于 HDFS 上通常存储的都是压缩文件,loader 也提供了对压缩文件的支持,并且本地磁盘文件或目录同样支持压缩文件。

目前支持的压缩文件类型包括:GZIP、BZ2、XZ、LZMA、SNAPPY_RAW、SNAPPY_FRAMED、Z、DEFLATE、LZ4_BLOCK、LZ4_FRAMED、ORC 和 PARQUET。

3.2.1.3 主流关系型数据库

loader 还支持以部分关系型数据库作为数据源,目前支持 MySQL、PostgreSQL、Oracle 和 SQL Server。

Loader 解析一行数据时,不会根据外键再查询其他表。输入行必须直接提供构造图元素所需的值。 需要关联数据时,先在数据源侧准备好查询结果。

以下以 person、software、created 三张表为例。

1// person 表结构
2id | name | age | city 
1// software 表结构
2id | name | lang | price
1// created 表结构
2id | p_id | s_id | date

若 person 和 software 使用 PRIMARY_KEY 策略,以 name 为主键,导入边时就需要两个端点的 name。 created 表只有 p_id 和 s_id,Loader 不会用它们回查名称。可以改用以下两种 ID 设计。

  1. 保留 PRIMARY_KEY 策略,将两张顶点表的 id 列作为主键属性。Loader 可用 p_id、s_id 和顶点标签生成端点 ID。
  2. 使用自定义 ID 策略,将两张顶点表的 id 列直接作为顶点 ID,导入边时直接使用 p_id 和 s_id。

这两种设计都让边数据直接提供端点 ID,省去回查。

3.2.2 准备顶点和边数据
3.2.2.1 顶点数据

顶点数据文件由一行一行的数据组成,一般每一行作为一个顶点,每一列会作为顶点属性。下面以 CSV 格式作为示例进行说明。

  • person 顶点数据(数据本身不包含 header)
1Tom,48,Beijing
2Jerry,36,Shanghai
  • software 顶点数据(数据本身包含 header)
1name,price
2Photoshop,999
3Office,388
3.2.2.2 边数据

边数据文件由一行一行的数据组成,一般每一行作为一条边,其中有部分列会作为源顶点和目标顶点的 id,其他列作为边属性。下面以 JSON 格式作为示例进行说明。

  • knows 边数据
1{"source_name": "Tom", "target_name": "Jerry", "date": "2008-12-12"}
  • created 边数据
1{"source_name": "Tom", "target_name": "Photoshop"}
2{"source_name": "Tom", "target_name": "Office"}
3{"source_name": "Jerry", "target_name": "Office"}

3.3 编写数据源映射文件

3.3.1 映射文件概述

映射文件使用 JSON 格式。每个 structs 映射块包含一个 input,以及该输入对应的 vertices 和 edges 映射。

input 描述数据位置、格式和分隔符。顶点和边映射指定标签、ID、属性及字段转换。

Loader 0.11.0 起使用 2.0 映射格式,此前的格式称为 1.0。下文未特别说明时,均使用 2.0 格式。

点击展开/折叠 2.0 版本的映射文件的框架
 1{
 2  "version": "2.0",
 3  "structs": [
 4    {
 5      "id": "1",
 6      "input": {
 7      },
 8      "vertices": [
 9        {},
10        {}
11      ],
12      "edges": [
13        {},
14        {}
15      ]
16    }
17  ]
18}

这里直接给出两个版本的映射文件(描述了上面图模型和数据文件)

点击展开/折叠 2.0 版本的映射文件
  1{
  2  "version": "2.0",
  3  "structs": [
  4    {
  5      "id": "1",
  6      "skip": false,
  7      "input": {
  8        "type": "FILE",
  9        "path": "vertex_person.csv",
 10        "file_filter": {
 11          "extensions": [
 12            "*"
 13          ]
 14        },
 15        "format": "CSV",
 16        "delimiter": ",",
 17        "date_format": "yyyy-MM-dd HH:mm:ss",
 18        "time_zone": "GMT+8",
 19        "skipped_line": {
 20          "regex": "(^#|^//).*|"
 21        },
 22        "compression": "NONE",
 23        "header": [
 24          "name",
 25          "age",
 26          "city"
 27        ],
 28        "charset": "UTF-8",
 29        "list_format": {
 30          "start_symbol": "[",
 31          "elem_delimiter": "|",
 32          "end_symbol": "]"
 33        }
 34      },
 35      "vertices": [
 36        {
 37          "label": "person",
 38          "skip": false,
 39          "id": null,
 40          "unfold": false,
 41          "field_mapping": {},
 42          "value_mapping": {},
 43          "selected": [],
 44          "ignored": [],
 45          "null_values": [
 46            ""
 47          ],
 48          "update_strategies": {}
 49        }
 50      ],
 51      "edges": []
 52    },
 53    {
 54      "id": "2",
 55      "skip": false,
 56      "input": {
 57        "type": "FILE",
 58        "path": "vertex_software.csv",
 59        "file_filter": {
 60          "extensions": [
 61            "*"
 62          ]
 63        },
 64        "format": "CSV",
 65        "delimiter": ",",
 66        "date_format": "yyyy-MM-dd HH:mm:ss",
 67        "time_zone": "GMT+8",
 68        "skipped_line": {
 69          "regex": "(^#|^//).*|"
 70        },
 71        "compression": "NONE",
 72        "header": null,
 73        "charset": "UTF-8",
 74        "list_format": {
 75          "start_symbol": "",
 76          "elem_delimiter": ",",
 77          "end_symbol": ""
 78        }
 79      },
 80      "vertices": [
 81        {
 82          "label": "software",
 83          "skip": false,
 84          "id": null,
 85          "unfold": false,
 86          "field_mapping": {},
 87          "value_mapping": {},
 88          "selected": [],
 89          "ignored": [],
 90          "null_values": [
 91            ""
 92          ],
 93          "update_strategies": {}
 94        }
 95      ],
 96      "edges": []
 97    },
 98    {
 99      "id": "3",
100      "skip": false,
101      "input": {
102        "type": "FILE",
103        "path": "edge_knows.json",
104        "file_filter": {
105          "extensions": [
106            "*"
107          ]
108        },
109        "format": "JSON",
110        "delimiter": null,
111        "date_format": "yyyy-MM-dd HH:mm:ss",
112        "time_zone": "GMT+8",
113        "skipped_line": {
114          "regex": "(^#|^//).*|"
115        },
116        "compression": "NONE",
117        "header": null,
118        "charset": "UTF-8",
119        "list_format": null
120      },
121      "vertices": [],
122      "edges": [
123        {
124          "label": "knows",
125          "skip": false,
126          "source": [
127            "source_name"
128          ],
129          "unfold_source": false,
130          "target": [
131            "target_name"
132          ],
133          "unfold_target": false,
134          "field_mapping": {
135            "source_name": "name",
136            "target_name": "name"
137          },
138          "value_mapping": {},
139          "selected": [],
140          "ignored": [],
141          "null_values": [
142            ""
143          ],
144          "update_strategies": {}
145        }
146      ]
147    },
148    {
149      "id": "4",
150      "skip": false,
151      "input": {
152        "type": "FILE",
153        "path": "edge_created.json",
154        "file_filter": {
155          "extensions": [
156            "*"
157          ]
158        },
159        "format": "JSON",
160        "delimiter": null,
161        "date_format": "yyyy-MM-dd HH:mm:ss",
162        "time_zone": "GMT+8",
163        "skipped_line": {
164          "regex": "(^#|^//).*|"
165        },
166        "compression": "NONE",
167        "header": null,
168        "charset": "UTF-8",
169        "list_format": null
170      },
171      "vertices": [],
172      "edges": [
173        {
174          "label": "created",
175          "skip": false,
176          "source": [
177            "source_name"
178          ],
179          "unfold_source": false,
180          "target": [
181            "target_name"
182          ],
183          "unfold_target": false,
184          "field_mapping": {
185            "source_name": "name",
186            "target_name": "name"
187          },
188          "value_mapping": {},
189          "selected": [],
190          "ignored": [],
191          "null_values": [
192            ""
193          ],
194          "update_strategies": {}
195        }
196      ]
197    }
198  ]
199}

点击展开/折叠 1.0 版本的映射文件
 1{
 2  "vertices": [
 3    {
 4      "label": "person",
 5      "input": {
 6        "type": "file",
 7        "path": "vertex_person.csv",
 8        "format": "CSV",
 9        "header": ["name", "age", "city"],
10        "charset": "UTF-8"
11      }
12    },
13    {
14      "label": "software",
15      "input": {
16        "type": "file",
17        "path": "vertex_software.csv",
18        "format": "CSV"
19      }
20    }
21  ],
22  "edges": [
23    {
24      "label": "knows",
25      "source": ["source_name"],
26      "target": ["target_name"],
27      "input": {
28        "type": "file",
29        "path": "edge_knows.json",
30        "format": "JSON"
31      },
32      "field_mapping": {
33        "source_name": "name",
34        "target_name": "name"
35      }
36    },
37    {
38      "label": "created",
39      "source": ["source_name"],
40      "target": ["target_name"],
41      "input": {
42        "type": "file",
43        "path": "edge_created.json",
44        "format": "JSON"
45      },
46      "field_mapping": {
47        "source_name": "name",
48        "target_name": "name"
49      }
50    }
51  ]
52}

映射文件 1.0 版本是以顶点和边为中心,设置输入源;而 2.0 版本是以输入源为中心,设置顶点和边映射。有些输入源(比如一个文件)既能生成顶点,也能生成边,如果用 1.0 版的格式写,就需要在 vertex 和 edge 映射块中各写一次 input 块,这两次的 input 块是完全一样的;而 2.0 版本只需要写一次 input。所以 2.0 版相比于 1.0 版,能省掉一些 input 的重复书写。

在 hugegraph-loader-{version} 的 bin 目录下,有一个脚本工具 mapping-convert.sh 能直接将 1.0 版本的映射文件转换为 2.0 版本的,使用方式如下:

1bin/mapping-convert.sh struct.json

会在 struct.json 的同级目录下生成一个 struct-v2.json。

bin 目录下还提供了 utf8-bom-to-utf8.sh,用于去掉单个数据文件、或目录下所有文件开头的 UTF-8 BOM。当 Windows 工具导出的 CSV 或 TEXT 文件因为首列表头带有不可见的 BOM 而解析失败时,可以用它处理:

1bin/utf8-bom-to-utf8.sh /path/to/file-or-dir
3.3.2 输入源

输入源目前分为五类:FILE、HDFS、JDBC、KAFKA 和 GRAPH,由type节点区分,我们称为本地文件输入源、HDFS 输入源、JDBC 输入源和 KAFKA 输入源,图数据源,下面分别介绍。

3.3.2.1 本地文件输入源
  • id: 输入源的 id,该字段用于支持一些内部功能,非必填(未填时会自动生成),强烈建议写上,对于调试大有裨益;
  • skip: 是否跳过该输入源,由于 JSON 文件无法添加注释,如果某次导入时不想导入某个输入源,但又不想删除该输入源的配置,则可以设置为 true 将其跳过,默认为 false,非必填;
  • input: 输入源映射块,复合结构
    • type: 输入源类型,必须填 file 或 FILE;
    • path: 本地文件或目录的路径,绝对路径或相对于 Loader 进程当前工作目录的相对路径,必填;为避免工作目录不同导致找不到文件,建议使用绝对路径;
    • file_filter: 从path中筛选复合条件的文件,复合结构,目前只支持配置扩展名,用子节点extensions表示,默认为"*",表示保留所有文件;
    • format: 本地文件的格式,可选值为 CSV、TEXT 及 JSON,必须大写,默认为 CSV,选填;
    • header: 文件各列的列名,如不指定则以数据文件第一行作为 header;显式指定时,首行若与 header 完全相同,默认仍会跳过,详见 has_header;JSON 文件不需要指定 header,选填;
    • has_header: 对 CSV 和 TEXT 格式,如果某个文件的首行与 header 完全相同,该行会被丢弃,这样目录下每个分片文件重复的表头不会被当作数据导入。如果分片文件的首行是恰好与 header 相同的真实数据,可以设为 false 关闭这个检查,选填;
    • delimiter: 文件行的列分隔符。默认值取决于format:CSV 为逗号",",TEXT 为制表符"\t";CSV 只接受逗号。JSON文件不需要指定,选填;
    • charset: 文件的编码字符集,默认UTF-8,选填;
    • date_format: 自定义的日期格式,默认值为 yyyy-MM-dd HH:mm:ss,选填;如果日期是以时间戳的形式呈现的,此项须写为timestamp(固定写法);
    • extra_date_formats: 备用日期格式列表,当某个值不符合date_format时会逐个尝试,默认为空,选填;
    • time_zone: 设置日期数据是处于哪个时区的,默认值为GMT+8,选填;
    • skipped_line: 想跳过的行,复合结构,目前只能配置要跳过的行的正则表达式,用子节点regex描述。默认正则为(^#|^//).*|,即跳过以#或//开头的行以及空行;如果需要保留这类行,把regex改为一个不匹配任何行的表达式即可,选填;
    • compression: 文件的压缩格式,可选值为 NONE、GZIP、BZ2、XZ、LZMA、SNAPPY_RAW、SNAPPY_FRAMED、Z、DEFLATE、LZ4_BLOCK、LZ4_FRAMED、ORC 和 PARQUET,默认为 NONE,表示非压缩文件,选填;ORC 和 PARQUET 的 header 匹配不区分大小写;
    • list_format: 当文件 (非 JSON ) 的某列是集合结构时(对应图中的 PropertyKey 的 Cardinality 为 Set 或 List),可以用此项设置该列的起始符、分隔符、结束符,复合结构:
      • start_symbol: 集合结构列的起始符 (默认值是空字符串 "", JSON 格式目前不支持指定)
      • elem_delimiter: 集合结构列的分隔符 (默认值是 |, 且不能与delimiter相同; JSON 格式目前只支持原生,分隔)
      • end_symbol: 集合结构列的结束符 (默认值是空字符串 "", JSON 格式目前不支持指定)
      • ignored_elems: 拆分之后要丢弃的元素,默认值是 [""],即忽略空元素
3.3.2.2 HDFS 输入源

上述本地文件输入源的节点及含义这里基本都适用,下面仅列出 HDFS 输入源不一样的和特有的节点。

  • type: 输入源类型,必须填 hdfs 或 HDFS,必填;
  • path: HDFS 文件或目录的路径,必须是 HDFS 的绝对路径,必填;
  • core_site_path: HDFS 集群的 core-site.xml 文件路径,重点要指明 NameNode 的地址(fs.default.name),以及文件系统的实现(fs.hdfs.impl),必填;
  • hdfs_site_path: HDFS 集群的 hdfs-site.xml 文件路径,选填;
  • dir_filter: 当path是目录时,决定递归进入哪些子目录,复合结构,选填:
    • include_regex: 只读取目录名匹配该正则的目录,默认为空,即不作限制;
    • exclude_regex: 跳过目录名匹配该正则的目录,默认为空;
  • kerberos_config: 访问开启了 Kerberos 认证的 HDFS 集群时的配置,复合结构,选填:
    • enable: 是否使用 Kerberos 认证,默认为 false;
    • krb5_conf: krb5.conf 文件路径,enable 为 true 时必填;
    • principal: Kerberos principal,enable 为 true 时必填;
    • keytab: keytab 文件路径,enable 为 true 时必填;
3.3.2.3 JDBC 输入源

前面说到过支持多种关系型数据库,但由于它们的映射结构非常相似,故统称为 JDBC 输入源,然后用vendor节点区分不同的数据库。

  • type: 输入源类型,必须填 jdbc 或 JDBC,必填;
  • vendor: 数据库类型,可选项为 [MySQL、PostgreSQL、Oracle、SQLServer],不区分大小写,必填;
  • driver: JDBC driver 类名,选填;不填时使用vendor对应的默认 driver,见下面各表;
  • url: jdbc 要连接的数据库的 url,必填;
  • database: 要连接的数据库名,必填;
  • schema: 要连接的 schema 名,不同的数据库要求不一样,下面详细说明;
  • table: 要连接的表名,custom_sql 和 table 参数必须填其中一个;
  • custom_sql: 自定义 SQL 语句,custom_sql 和 table 参数必须填其中一个;
  • username: 连接数据库的用户名,必填;
  • password: 连接数据库的密码,必填;
  • where: 附加到生成的 select 语句上的过滤条件,不需要写 where 关键字,选填;
  • batch_size: 按页获取表数据时的一页的大小,默认为 500,选填;

MYSQL

节点固定值或常见值
vendorMYSQL
drivercom.mysql.cj.jdbc.Driver
urljdbc:mysql://127.0.0.1:3306

schema: 可空,若填写必须与 database 的值一样

POSTGRESQL

节点固定值或常见值
vendorPOSTGRESQL
driverorg.postgresql.Driver
urljdbc:postgresql://127.0.0.1:5432

schema: 可空,默认值为“public”

ORACLE

节点固定值或常见值
vendorORACLE
driveroracle.jdbc.driver.OracleDriver
urljdbc:oracle:thin:@127.0.0.1:1521

schema: 可空,默认值为大写形式的用户名

SQLSERVER

节点固定值或常见值
vendorSQLSERVER
drivercom.microsoft.sqlserver.jdbc.SQLServerDriver
urljdbc:sqlserver://127.0.0.1:1433

schema: 必填

3.3.2.4 Kafka 输入源
  • type:输入源类型,必须填 kafka 或 KAFKA,必填;
  • bootstrap_server:kafka bootstrap server 列表,必填;
  • topic:订阅的 topic,必填;
  • group:Kafka 消费者组,必填;
  • from_beginning:设置 Kafka 的 auto.offset.reset;true 对应 earliest,false 对应 latest,默认为 false。该策略仅在消费组没有已提交 offset,或已提交 offset 不再有效时生效;已有有效 offset 时会从该 offset 继续读取;
  • format:每条消息的格式,可选值为 CSV、TEXT 及 JSON,必须大写,必填;
  • header:消息各列的列名;loader 不会从 topic 中读取表头行,因此 CSV 和 TEXT 格式必须指定,JSON 消息则不需要;
  • delimiter:消息的列分隔符,仅 TEXT 格式使用,CSV 固定以,分隔,选填;
  • charset:消息的编码字符集,默认 UTF-8,选填;
  • date_format:自定义的日期格式,默认值为 yyyy-MM-dd HH:mm:ss,选填;如果日期是以时间戳的形式呈现的,此项须写为 timestamp(固定写法);
  • extra_date_formats:自定义的其他日期格式列表,默认为空,选填;列表中每一项都是一个 date_format 指定日期格式的备用日期格式;
  • time_zone:置日期数据是处于哪个时区的,默认值为 GMT+8,选填;
  • skipped_line:当前 master 的 KafkaReader 未实现该过滤,配置此字段不会跳过 Kafka 消息;每条消息仍会直接交给所选格式的解析器,空行或注释行可能因此触发解析错误。需要过滤时请在写入 Kafka 前或消费侧预处理;
  • batch_size:单次拉取的最大记录数(max.poll.records),默认为 500,选填;
  • early_stop:某次从 Kafka broker 拉取的记录为空,停止任务,默认为 false,仅用于调试,选填;
3.3.2.5 GRAPH 输入源

GRAPH 输入源从另一个 HugeGraph 图(通过 HugeGraph-PD 访问)读取顶点和边,并写入目标图。当映射文件中出现 GRAPH 输入源时,该文件中所有未被跳过的输入源都必须是 GRAPH 类型,并且导入期间 loader 会把目标图切换为 RESTORING 模式。

  • type:输入源类型,必须填 graph 或 GRAPH,必填;
  • graphspace:源图空间名称,必填;
  • graph: 源图名称,必填;
  • username:HugeGraph 用户名;为空时使用命令行参数 --username;
  • password:HugeGraph 密码;为空时使用命令行参数 --password;
  • selected_vertices:要复制的顶点 label 列表,每一项形如 {"label": "...", "properties": [...], "query": {...}},其中 properties 限定要复制的属性,query 是传给源图的可选过滤条件;
  • ignored_vertices:要跳过的顶点 label 列表,每一项形如 {"label": "...", "properties": [...]};
  • selected_edges:要复制的边 label 列表,每一项结构与 selected_vertices 相同;
  • ignored_edges:要跳过的边 label 列表,每一项结构与 ignored_vertices 相同;
  • pd-peers:源集群的 HugeGraph-PD 节点地址;为空时使用 --pd-peers;
  • meta-endpoints:源集群 Meta 服务端点;为空时使用 --meta-endpoints;
  • cluster:源集群名称;为空时使用 --cluster;
  • batch_size:批量读取源图数据的批次大小,默认为500;
3.3.3 顶点和边映射

顶点和边映射的节点(JSON 文件中的一个 key)有很多相同的部分,下面先介绍相同部分,再分别介绍顶点映射和边映射的特有节点。

相同部分的节点

  • label: 待导入的顶点/边数据所属的label,必填;
  • skip: 是否跳过该顶点/边映射,输入源和其他映射不受影响,默认为 false,选填;
  • field_mapping: 将输入源列的列名映射为顶点/边的属性名,选填;
  • value_mapping: 将输入源的数据值映射为顶点/边的属性值,选填;
  • selected: 选择某些列插入,其他未选中的不插入,不能与ignored同时存在,选填;
  • ignored: 忽略某些列,使其不参与插入,不能与selected同时存在,选填;
  • null_values: 可以指定一些字符串代表空值,比如"NULL",如果该列对应的顶点/边属性又是一个可空属性,那在构造顶点/边时不会设置该属性的值,选填;
  • update_strategies: 如果数据需要按特定方式批量更新时可以对每个属性指定具体的更新策略 (具体见下),选填;
  • unfold: 是否将列展开,展开的每一列都会与其他列一起组成一行,相当于是展开成了多行;比如文件的某一列(id 列)的值是[1,2,3],其他列的值是18,Beijing,当设置了 unfold 之后,这一行就会变成 3 行,分别是:1,18,Beijing,2,18,Beijing和3,18,Beijing。需要注意的是此项只会展开被选作为 id 的列。默认 false,选填;

更新策略支持 8 种 : (需要全大写)

  1. 数值累加 : SUM
  2. 两个数字/日期取更大的: BIGGER
  3. 两个数字/日期取更小: SMALLER
  4. Set属性取并集:UNION
  5. Set属性取交集:INTERSECTION
  6. List属性追加元素:APPEND
  7. List/Set属性删除元素:ELIMINATE
  8. 覆盖已有属性:OVERRIDE

注意: 如果新导入的属性值为空,会采用已有的旧数据而不会采用空值,效果可以参考如下示例

 1// JSON 文件中以如下方式指定更新策略
 2{
 3  "vertices": [
 4    {
 5      "label": "person",
 6      "update_strategies": {
 7        "age": "SMALLER",
 8        "set": "UNION"
 9      },
10      "input": {
11        "type": "file",
12        "path": "vertex_person.txt",
13        "format": "TEXT",
14        "header": ["name", "age", "set"]
15      }
16    }
17  ]
18}
19
20// 1.写入一行带 OVERRIDE 更新策略的数据 (这里 null 代表空)
21'a b null null'
22
23// 2.再写一行
24'null null c d'
25
26// 3.最后可以得到
27'a b c d'   
28
29// 如果没有更新策略,则会得到
30'null null c d'

注意 : 采用了批量更新的策略后, 磁盘读请求数会大幅上升, 导入速度相比纯写覆盖会慢数倍 (此时HDD磁盘IOPS会成为瓶颈, 建议采用SSD以保证速度)

顶点映射的特有节点

  • id: 指定某一列作为顶点的 id 列,当顶点 id 策略为CUSTOMIZE时,必填;当 id 策略为PRIMARY_KEY时,必须为空;

边映射的特有节点

  • source: 选择输入源某几列作为源顶点的 id 列,当源顶点的 id 策略为 CUSTOMIZE时,必须指定某一列作为顶点的 id 列;当源顶点的 id 策略为 PRIMARY_KEY时,必须指定一列或多列用于拼接生成顶点的 id,也就是说,不管是哪种 id 策略,此项必填;
  • target: 指定某几列作为目标顶点的 id 列,与 source 类似,不再赘述;
  • unfold_source: 是否展开文件的 source 列,效果与顶点映射中的类似,不再赘述;
  • unfold_target: 是否展开文件的 target 列,效果与顶点映射中的类似,不再赘述;

3.4 执行命令导入

准备好图模型、数据文件以及输入源映射关系文件后,接下来就可以将数据文件导入到图数据库中。

导入过程由用户提交的命令控制,用户可以通过不同的参数控制执行的具体流程。

3.4.1 参数说明
参数默认值是否必传描述信息
-f 或 --fileY配置脚本的路径
-g 或 --graphhugegraph图名称
--graphspaceDEFAULT图空间
-s 或 --schemaschema 文件路径;已有 Schema 时可以不传
-h 或 --host 或 -ilocalhostHugeGraphServer 的地址
-p 或 --port8080HugeGraphServer 的端口号
--usernamenull当 HugeGraphServer 开启了权限认证时,当前图的 username
--passwordnull当 HugeGraphServer 开启了权限认证时,当前图的 password
--create-graphfalse是否在图不存在时自动创建
--tokennull当 HugeGraphServer 开启了权限认证时,当前图的 token
--protocolhttp向服务端发请求的协议,可选 http 或 https
--pd-peersPD 服务节点地址
--pd-token访问 PD 服务的 token
--meta-endpoints元信息存储服务地址
--directfalse当前 master 未启用 Store 直连,仍经 Server API 导入;保留默认值
--route-typeNODE_PORT路由选择方式(可选值:NODE_PORT / DDS / BOTH)
--clusterhg集群名
--trust-store-file请求协议为 https 时,客户端的证书文件路径
--trust-store-password请求协议为 https 时,客户端证书密码
--clear-all-datafalse导入数据前是否清除服务端的原有数据
--clear-timeout240导入数据前清除服务端的原有数据的超时时间
--incremental-modefalse是否使用断点续导模式,仅输入源为 FILE 和 HDFS 支持该模式,启用该模式能从上一次导入停止的地方开始导入
--failure-modefalse失败模式为 true 时,会导入之前失败了的数据,一般来说失败数据文件需要在人工更正编辑好后,再次进行导入
--batch-insert-threadsCPUs批量插入线程池大小 (CPUs 是当前 OS 可用逻辑核个数)
--single-insert-threads8单条插入线程池的大小
--max-conn4 * CPUsHugeClient 与 HugeGraphServer 的最大 HTTP 连接数;保持默认值时会自动提升到 4 * --batch-insert-threads
--max-conn-per-route2 * CPUsHugeClient 与 HugeGraphServer 每个路由的最大 HTTP 连接数;保持默认值时会自动提升到 2 * --batch-insert-threads
--batch-size500导入数据时每个批次包含的数据条数
--max-parse-errors1最多允许多少行数据解析错误,达到该值则程序退出
--max-insert-errors500最多允许多少行数据插入错误,达到该值则程序退出
--timeout60插入结果返回的超时时间(秒)
--shutdown-timeout10多线程停止的等待时间(秒)
--retry-times3发生超时时的最大重试次数
--retry-interval10重试之前的间隔时间(秒)
--check-vertexfalse插入边时是否检查边所连接的顶点是否存在
--print-progresstrue是否在控制台实时打印导入条数
--dry-runfalse打开该模式,只解析不导入,通常用于测试
--help 或 -helpfalse打印帮助信息
--parser-threads 或 --parallel-countmax(2,CPUs/2)并行读取管线数;--parallel-count 已弃用
--start-file0用于部分(分片)导入的起始文件索引
--end-file-1用于部分导入的截止文件索引
--scatter-sourcesfalse分散(并行)读取多个数据源以优化 I/O 性能
--cdc-flush-interval30000Flink CDC 的数据刷新间隔
--cdc-sink-parallelism1Flink CDC 写入端(Sink)的并行度
--max-read-errors1程序退出前允许的最大读取错误行数
--max-read-lines-1L最大读取行数限制;一旦达到此行数,导入任务将停止
--test-modefalse是否开启测试模式
--use-prefilterfalse是否预先过滤顶点
--short-id将自定义顶点 ID 映射为更短的生成 ID,格式为 label:field:type,其中 type 可选 boolean、byte、int、long、float、double、text、blob、date、uuid;可以重复指定以覆盖多个 label
--vertex-edge-limit-1L单个顶点的最大边数限制
--sink-typetrue仅 spark-loader 使用:true 通过 HugeGraph server API 写入,false 生成 HFile 并直接 bulkload 到 HBase
--vertex-partitions64HBase 顶点表的预分区数量,配合 --sink-type false 使用
--edge-partitions64HBase 边表的预分区数量,配合 --sink-type false 使用
--vertex-table-nameHBase 顶点表名称,配合 --sink-type false 使用
--edge-table-nameHBase 边表名称,配合 --sink-type false 使用
--hbase-zk-quorumHBase Zookeeper 集群地址,配合 --sink-type false 使用
--hbase-zk-portHBase Zookeeper 端口号,配合 --sink-type false 使用
--hbase-zk-parentHBase Zookeeper 根路径,配合 --sink-type false 使用
--restorefalse将图模式设置为恢复模式 (RESTORING)
--backendhstore自动创建图(如果不存在)时的后端存储类型
--serializerbinary自动创建图(如果不存在)时的序列化器类型
--scheduler-typedistributed自动创建图(如果不存在)时的任务调度器类型
--batch-failure-fallbacktrue批量插入失败时是否回退至单条插入模式

映射文件选项 --file(-f)是必填项,其他选项使用默认值。有效的最简调用为:

1bin/hugegraph-loader.sh --file struct.json

启动脚本也支持 JCommander 原生的 @file 语法。在 loader.args 中把每个选项及其值分别写在单独一行:

1--file
2struct.json
1bin/hugegraph-loader.sh @loader.args

这与上面的最简调用等价。参数中的相对路径以 Loader 进程的工作目录为基准。 若参数文件包含凭据,使用 chmod 0600 loader.args 把权限限制为 0600;@file 调用让这些值不出现在进程参数中。 Loader 必须能够创建并写入以映射文件前缀命名的进度目录。 从只读 Kubernetes ConfigMap 挂载映射文件时,先把映射复制到可写卷中再运行 Loader。

3.4.2 断点续导模式

通常情况下,Loader 任务都需要较长时间执行,如果因为某些原因导致导入中断进程退出,而下次希望能从中断的点继续导,这就是使用断点续导的场景。

设置 --incremental-mode 为 true 即可从进度文件续导。Loader 在导入成功或正常停止后关闭时写入进度;意外失败可能阻止该写入。 进度文件位于 ${struct} 目录下,文件名形如 load-progress_${timestamp} ,${struct} 为映射文件的前缀,${timestamp} 为导入开始 的时刻,格式为 yyyyMMdd-HHmmss。比如:在 2019-10-10 12:30:30 开始的一次导入任务,使用的映射文件为 struct-example.json,则进度文件的路径为与 struct-example.json 同级的 struct-example/load-progress_20191010-123030。当目录下存在多个进度文件时,续导会读取按文件名排序的最后一个,也就是最新的那个。

注意:导入成功或正常停止(包括达到错误上限)后会写入进度文件,与 --incremental-mode 或 --print-progress 是否打开无关。 意外失败导致导入中止时,可能不会写入进度文件。

如果数据文件格式都是合法的,是用户自己停止(CTRL + C 或 kill,kill -9 不支持)的导入任务,也就是说没有错误记录的情况下,下一次导入只需要设置为断点续导即可。

但如果是因为太多数据不合法或者网络异常,达到了 –max-read-errors、–max-parse-errors 或 –max-insert-errors 的限制,Loader 会把这些失败的原始行记录到 失败文件中,用户对失败文件中的数据行修改后,设置 –failure-mode 为 true 即可把这些"失败文件"也当作输入源进行导入(不影响正常的文件的导入), 当然如果修改后的数据行仍然有问题,则会被再次记录到失败文件中(不用担心会有重复行,关闭文件时会去重)。失败模式下上述三个错误上限会被解除,因此会扫描整个失败文件。

每个输入源(即映射文件 structs 中的每一项)都会有自己的失败文件,文件名为该输入源的 id 加后缀 .error,保存在 ${struct}/failure-data 目录下。 每一条失败记录写为两行:一行以 #### READ ERROR:、#### PARSE ERROR: 或 #### INSERT ERROR: 开头的提示行,紧接着是原始数据行。当输入源有 header 时,header 会以 JSON 形式写入同目录下的 ${id}.header 文件,以便失败文件能按正确的列重新读取。 比如映射文件中 id 为 1 的输入源包含顶点映射 person,id 为 3 的输入源包含边映射 knows,它们各有一些错误行,当 Loader 退出后,在 ${struct}/failure-data 目录下会看到如下文件:

  • 1.error: 输入源 1 的失败数据行,每行前面都有对应的提示行
  • 1.header: 输入源 1 的 header,仅当该输入源有 header 时才会生成
  • 3.error: 输入源 3 的失败数据行
  • 3.header: 输入源 3 的 header

内容为空的 .error 文件会在 Loader 退出时删除,因此只有真正出现失败行的输入源才会留下文件。增量模式下新的失败行会追加到已有文件,其他模式下该文件会被重新写入。

3.4.3 logs 目录文件说明

程序执行过程中各日志及错误数据会写入 hugegraph-loader.log 文件中。

3.4.4 执行命令

运行 bin/hugegraph-loader.sh 并传入参数

1bin/hugegraph-loader.sh -g {GRAPH_NAME} -f ${INPUT_DESC_FILE} -s ${SCHEMA_FILE} -h {HOST} -p {PORT}

脚本在设置了 JAVA_HOME 时使用其中的 JVM,否则使用 PATH 上的 java。它会把 JVM_OPTS 环境变量的内容,以及 -Xmx10g 和由 lib/ 生成的 classpath 一起传给 JVM,因此需要追加 JVM 参数时可以设置 JVM_OPTS。日志由 conf/log4j2.xml 配置。

3.4.5 最小本地文件导入示例

按本页开头的本地文件导入步骤操作。

3.4.6 并发导入与 LOADING owner

在 master 分支中,Loader 为普通导入实现了 LOADING 所有权管理协议,与 Server 的 /mode/owners 接口协同工作。 若部署的 Server 提供该接口并返回 protocol: 1,Loader 会自动启用所有权保护;已发布的 Server 1.7.0 及更早版本则继续使用原有模式切换流程。

graph TD
    A["图模式 NONE"] -->|首个 Loader 申请所有权| B["进入 LOADING 模式 (分配 token)"]
    B -->|其他并发 Loader 加入| B
    B -->|部分 Loader 导入完成释放| B
    B -->|最后一个 Loader 释放| C["自动恢复 NONE 模式"]
    B -.->|"异常/进程中断 (Token 残留)"| D["管理员恢复 / 释放 / 重启图实例"]
    D -.->|"最后一个 owner 释放,或 recover/重启"| A
    D -.->|"仍有其他 owner 活跃"| B
  1. 探测与获取:Loader 启动后探测 /mode/owners。首个 Loader 获取所有权句柄(instance/epoch/token),图模式由 NONE 转为 LOADING;并发 Loader 可申请加入该模式。
  2. 数据导入:持有有效句柄的 Loader 并行执行数据导入。
  3. 安全释放:导入完成后停止 worker 并释放对应句柄。当最后一个 owner 释放时,图模式自动恢复为 NONE。
  4. 异常恢复:若因异常中断(如 kill -9)导致句柄残留,请先停止并排空所有相关的导入任务与图写操作, 然后通过 RESTful API 管理员恢复接口 执行恢复,或重启 Server。 直接调用 release 仅适用于仍持有 Token 的调用方(如直接调用 REST API 的客户端)。
说明

兼容性与运维说明

  • 旧版本兼容:普通导入时仅在接口返回不支持该路由的 404 响应时回退至旧版 LOADING/NONE 枚举流程(支持 1.7 等旧版 Server,但不提供并发隔离)。 权限、网络、图不存在或无效响应错误不会触发回退。
  • 恢复与图源导入:保留 RESTORING 模式,不探测 owner 且不自动重置。恢复导入完成后须手动将图模式设回 NONE,否则后续普通导入无法获取首个所有权。 在活跃 owner 存在期间,请勿运行恢复导入、图源导入、Spark connector 或旧版 Loader 导入。
  • 作用范围与生命周期:所有权属于直连 Server 实例,不跨节点同步;owner 无自动租期过期机制。 对于嵌入式程序集成,调用方必须调用 HugeGraphLoader.shutdown() 执行单次句柄释放;若释放失败,不会自动重试; 该 owner 可能会在 Server 端保持活跃,此时可能需要通过上述管理员恢复流程处理。

4 完整示例

下面给出的是 hugegraph-loader 包中 example 目录下的例子。(GitHub 地址)

4.1 准备数据

顶点文件:example/file/vertex_person.csv

1marko,29,Beijing
2vadas,27,Hongkong
3josh,32,Beijing
4peter,35,Shanghai
5"li,nary",26,"Wu,han"
6tom,null,NULL

顶点文件:example/file/vertex_software.txt

1id|name|lang|price|ISBN
21|lop|java|328|ISBN978-7-107-18618-5
32|ripple|java|199|ISBN978-7-100-13678-5

边文件:example/file/edge_knows.json

1{"source_name": "marko", "target_name": "vadas", "date": "20160110", "weight": 0.5}
2{"source_name": "marko", "target_name": "josh", "date": "20130220", "weight": 1.0}

边文件:example/file/edge_created.json

1{"source_name": "marko", "target_id": 1, "date": "2017-12-10", "weight": 0.4}
2{"source_name": "josh", "target_id": 1, "date": "2009-11-11", "weight": 0.4}
3{"source_name": "josh", "target_id": 2, "date": "2017-12-10", "weight": 1.0}
4{"source_name": "peter", "target_id": 1, "date": "2017-03-24", "weight": 0.2}

4.2 编写 schema

点击展开/折叠 schema 文件:example/file/schema.groovy
 1schema.propertyKey("name").asText().ifNotExist().create();
 2schema.propertyKey("age").asInt().ifNotExist().create();
 3schema.propertyKey("city").asText().ifNotExist().create();
 4schema.propertyKey("weight").asDouble().ifNotExist().create();
 5schema.propertyKey("lang").asText().ifNotExist().create();
 6schema.propertyKey("date").asText().ifNotExist().create();
 7schema.propertyKey("price").asDouble().ifNotExist().create();
 8
 9schema.vertexLabel("person").properties("name", "age", "city").primaryKeys("name").nullableKeys("age", "city").ifNotExist().create();
10schema.vertexLabel("software").useCustomizeNumberId().properties("name", "lang", "price").ifNotExist().create();
11
12schema.indexLabel("personByAge").onV("person").by("age").range().ifNotExist().create();
13schema.indexLabel("personByCity").onV("person").by("city").secondary().ifNotExist().create();
14schema.indexLabel("personByAgeAndCity").onV("person").by("age", "city").secondary().ifNotExist().create();
15schema.indexLabel("softwareByPrice").onV("software").by("price").range().ifNotExist().create();
16
17schema.edgeLabel("knows").sourceLabel("person").targetLabel("person").properties("date", "weight").ifNotExist().create();
18schema.edgeLabel("created").sourceLabel("person").targetLabel("software").properties("date", "weight").ifNotExist().create();
19
20schema.indexLabel("createdByDate").onE("created").by("date").secondary().ifNotExist().create();
21schema.indexLabel("createdByWeight").onE("created").by("weight").range().ifNotExist().create();
22schema.indexLabel("knowsByWeight").onE("knows").by("weight").range().ifNotExist().create();

person 使用 name 作为主键;Tom 的 age 和 city 会被 null_values 去掉,因此这两个属性必须允许为空。 software 使用自定义数值 ID,映射中的 id 和 created.target_id 分别对应顶点 ID 及边的目标 ID。 请在未包含同名 Schema 的空图中执行,避免 ifNotExist() 保留已有的不兼容定义。

4.3 编写输入源映射文件example/file/struct.json

点击展开/折叠 源映射文件 example/file/struct.json
 1{
 2  "vertices": [
 3    {
 4      "label": "person",
 5      "input": {
 6        "type": "file",
 7        "path": "example/file/vertex_person.csv",
 8        "format": "CSV",
 9        "header": ["name", "age", "city"],
10        "charset": "UTF-8",
11        "skipped_line": {
12          "regex": "(^#|^//).*"
13        }
14      },
15      "null_values": ["NULL", "null", ""]
16    },
17    {
18      "label": "software",
19      "input": {
20        "type": "file",
21        "path": "example/file/vertex_software.txt",
22        "format": "TEXT",
23        "delimiter": "|",
24        "charset": "GBK"
25      },
26      "id": "id",
27      "ignored": ["ISBN"]
28    }
29  ],
30  "edges": [
31    {
32      "label": "knows",
33      "source": ["source_name"],
34      "target": ["target_name"],
35      "input": {
36        "type": "file",
37        "path": "example/file/edge_knows.json",
38        "format": "JSON",
39        "date_format": "yyyyMMdd"
40      },
41      "field_mapping": {
42        "source_name": "name",
43        "target_name": "name"
44      }
45    },
46    {
47      "label": "created",
48      "source": ["source_name"],
49      "target": ["target_id"],
50      "input": {
51        "type": "file",
52        "path": "example/file/edge_created.json",
53        "format": "JSON",
54        "date_format": "yyyy-MM-dd"
55      },
56      "field_mapping": {
57        "source_name": "name"
58      }
59    }
60  ]
61}

4.4 执行命令导入

1sh bin/hugegraph-loader.sh -g hugegraph -f example/file/struct.json -s example/file/schema.groovy

导入结束后,会出现类似如下统计信息:

 1vertices/edges has been loaded this time : 8/6
 2--------------------------------------------------
 3count metrics
 4     input read success            : 14
 5     input read failure            : 0
 6     vertex parse success          : 8
 7     vertex parse failure          : 0
 8     vertex insert success         : 8
 9     vertex insert failure         : 0
10     edge parse success            : 6
11     edge parse failure            : 0
12     edge insert success           : 6
13     edge insert failure           : 0

4.5 使用 docker 导入

4.5.1 使用 docker exec 直接导入数据
4.5.1.1 数据准备

如果仅仅尝试使用 loader, 我们可以使用内置的 example 数据集进行导入,无需自己额外准备数据

如果使用自定义的数据,则在使用 loader 导入数据之前,我们需要将数据复制到容器内部。

首先我们可以根据 4.1-4.3 的步骤准备数据,将准备好的数据通过 docker cp 复制到 loader 容器内部。

假设我们已经按照上述的步骤准备好了对应的数据集,存放在 hugegraph-dataset 文件夹下,文件结构如下:

1tree -f hugegraph-dataset/
2
3hugegraph-dataset
4├── hugegraph-dataset/edge_created.json
5├── hugegraph-dataset/edge_knows.json
6├── hugegraph-dataset/schema.groovy
7├── hugegraph-dataset/struct.json
8├── hugegraph-dataset/vertex_person.csv
9└── hugegraph-dataset/vertex_software.txt

将文件复制到容器内部

1docker cp hugegraph-dataset loader:/loader/dataset
2docker exec -it loader ls /loader/dataset
3
4edge_created.json  edge_knows.json  schema.groovy  struct.json  vertex_person.csv  vertex_software.txt
4.5.1.2 数据导入

以内置的 example 数据集为例,我们可以使用以下的命令对数据进行导入。

如果需要导入自己准备的数据集,则只需要修改 -f 配置脚本的路径 以及 -s schema 文件路径即可。

其他的参数可以参照 3.4.1 参数说明

1docker exec -it loader bin/hugegraph-loader.sh -g hugegraph -f example/file/struct.json -s example/file/schema.groovy -h server -p 8080

如果导入用户自定义的数据集,按照刚才的例子,则使用:

1docker exec -it loader bin/hugegraph-loader.sh -g hugegraph -f /loader/dataset/struct.json -s /loader/dataset/schema.groovy -h server -p 8080

自定义数据集的 struct.json 还需将每个 input.path 改为容器内实际路径,例如 /loader/dataset/vertex_person.csv。 只修改 -f 和 -s 不会改变数据文件的解析路径。

如果 loader 和 server位于同一 docker 网络,则可以指定 -h {server_container_name}, 否则需要指定 server的宿主机的 ip (在我们的例子中, server_container_name 为 server).

然后我们可以观察到结果:

 1HugeGraphLoader worked in NORMAL MODE
 2vertices/edges loaded this time : 8/6
 3--------------------------------------------------
 4count metrics
 5    input read success            : 14                  
 6    input read failure            : 0                   
 7    vertex parse success          : 8                   
 8    vertex parse failure          : 0                   
 9    vertex insert success         : 8                   
10    vertex insert failure         : 0                   
11    edge parse success            : 6                   
12    edge parse failure            : 0                   
13    edge insert success           : 6                   
14    edge insert failure           : 0                   
15--------------------------------------------------
16meter metrics
17    total time                    : 0.199s              
18    read time                     : 0.046s              
19    load time                     : 0.153s              
20    vertex load time              : 0.077s              
21    vertex load rate(vertices/s)  : 103                 
22    edge load time                : 0.112s              
23    edge load rate(edges/s)       : 53   

也可以使用 curl 或者 hubble观察导入结果,此处以 curl 为例:

以下使用支持 GraphSpace 的 Server API;旧版 Server 的路径需去掉 /graphspaces/DEFAULT。

1curl --compressed "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices"
2{"vertices":[{"id":1,"label":"software","type":"vertex","properties":{"name":"lop","lang":"java","price":328.0}},{"id":2,"label":"software","type":"vertex","properties":{"name":"ripple","lang":"java","price":199.0}},{"id":"1:tom","label":"person","type":"vertex","properties":{"name":"tom"}},{"id":"1:josh","label":"person","type":"vertex","properties":{"name":"josh","age":32,"city":"Beijing"}},{"id":"1:marko","label":"person","type":"vertex","properties":{"name":"marko","age":29,"city":"Beijing"}},{"id":"1:peter","label":"person","type":"vertex","properties":{"name":"peter","age":35,"city":"Shanghai"}},{"id":"1:vadas","label":"person","type":"vertex","properties":{"name":"vadas","age":27,"city":"Hongkong"}},{"id":"1:li,nary","label":"person","type":"vertex","properties":{"name":"li,nary","age":26,"city":"Wu,han"}}]}

如果想检查边的导入结果,可以使用 curl --compressed "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/edges"

4.5.2 进入 docker 容器进行导入

除了直接使用 docker exec 导入数据,我们也可以进入容器进行数据导入,基本流程与 4.5.1 相同

使用 docker exec -it loader bash进入容器内部,并执行命令

1sh bin/hugegraph-loader.sh -g hugegraph -f example/file/struct.json -s example/file/schema.groovy -h server -p 8080

执行的结果如 4.5.1 所示

4.6 使用 spark-loader 导入

当前 master 分支的 API 写入路径使用 Spark 3.5.8、Scala 2.12,driver 和 executor 均需 Java 17。 POM 中的 Spark 3.2.2 只提供编译期 API,不是运行引擎。设置 SPARK_HOME 和 JAVA_HOME, 再使用发行目录中的启动脚本和 shaded Loader JAR。

先创建 Schema,确保 executor 可以读取数据文件。CSV、TEXT 数据须使用 UTF-8、去掉表头行,并在映射中显式指定 header。 其他字符集和 has_header: true 会被拒绝。边依赖已有顶点时,先导入顶点。将以下路径替换为准备好的顶点映射文件。

1bin/hugegraph-spark-loader.sh \
2  --master 'local[2]' --driver-memory 1g \
3  --file /path/to/vertex-mapping.json \
4  --host 127.0.0.1 --port 8080 --graph hugegraph --sink-type true

启动脚本可同时接收 --master、--conf、--jars 等 Spark 参数和 Loader 参数。 额外的 JDBC 驱动需通过 --jars 传入,仅放在 lib/ 中不会分发到 executor。 导入后查询目标图,核对数量和属性;API 写入路径的插入计数器不统计分布式写入。

该路径拒绝 --incremental-mode true 和 --failure-mode true。Standalone Spark 仅支持 client 部署模式。 Spark 3.5.8 / Java 17 不支持 HBase bulkload(--sink-type false)。已有 bulkload 部署建议继续沿用原环境验证通过的 Loader 发布包及其相关依赖。更多细节见 Spark 迁移说明。

当前 master 分支适配 Flink 2.2.1、MySQL CDC 3.6.0-2.2 和 Java 17。 此前使用 Flink 1.13.5、CDC 2.2.1 的示例属于旧实现。 设置 FLINK_HOME,确保提交进程、JobManager 和 TaskManager 都使用 Java 17。 保留 Flink 的模块访问参数,发行目录的 lib/ 中须恰好有一个 shaded Loader JAR。

每个映射都需使用 MySQL JDBC 输入,包含 url、database、table、username 和 password。 MySQL 须配置 binlog_row_image=FULL。UPDATE 事件需要显式指定非空的 update_strategies,且图元素标识保持不变。 顶点 ID、边端点或排序键变化时,任务会拒绝更新。CDC 也会拒绝 --dry-run true 和 --use-prefilter true。

不带分隔符时,所有参数均交给 Loader。需要设置 Flink 参数时,将其放在 -- 之前,Loader 参数放在之后。 准备好 mysql-cdc.json 映射后,使用单个 sink writer 提交任务。

1bin/hugegraph-flinkcdc-loader.sh -p 1 -- \
2  --file ./mysql-cdc.json --host 127.0.0.1 --port 8080 \
3  --graph hugegraph --cdc-sink-parallelism 1

每个映射使用一个 source reader 和一个 sink writer。--cdc-sink-parallelism 默认为 1,其他取值会被拒绝。 -- 之后的 Loader 参数 -p 表示 Server 端口。Checkpoint 刷新不提供图写入事务,也不保证 exactly-once。 在生产环境部署边 CDC 或更复杂的多表映射前,建议先在真实环境中充分验证。 支持范围和恢复流程见 Flink CDC 说明。

2.4 - 图导入

需要把文件、数据库或消息数据写入 HugeGraph 时,从这里选择工具。直接导入可使用 Loader;已有 Source、Transform、Sink 管道时使用 SeaTunnel Sink;Spark 作业可使用 Spark Connector。

2.4.1 - 使用 SeaTunnel Sink 导入图数据

SeaTunnel 可以把数据库、Kafka 等数据源接入 HugeGraph。连接器分为两部分:Source 负责读取,Sink 负责写入[1][2],中间可以接 SeaTunnel 的数据转换组件。需要从 HugeGraph 导出或迁移数据时,请查看SeaTunnel Source 导出与迁移文档。

版本要求:本文面向 SeaTunnel 3.0+。 所有示例使用 SeaTunnel 3.0+ 提供的 mappings 配置。

通过 HugeGraph Helm 部署时,可直接启用内置 SeaTunnel。 Chart 已预置 HugeGraph 连接器、运行环境及同 Release 的连接凭据;本页重点介绍接入外部数据源时的作业配置。

Loader 与 SeaTunnel 的工作流对比:直接导入图数据与复用 Source、Transform、Sink 管道

点击配图可查看原图。

1 与 Loader 和 Tools 的区别

HugeGraph-Loader 适合把常见数据直接导入 HugeGraph;HugeGraph-Tools 主要用于单机图管理、备份和导出;SeaTunnel 则把任务组织成 Source → Transform → Sink,适合复用已有的连接器、转换步骤和数据处理管道。

表格标记

✅ 原生支持;⚠️ 有条件支持,或需要额外组件/外部平台;❌ 不提供该能力

对比点LoaderToolsSeaTunnel
任务覆盖✅ 直接导入图数据✅ 备份、恢复和导出✅ 导入、导出与迁移,可组合 Source、Transform、Sink
任务配置JSON 映射文件,描述输入源、顶点和边命令行参数和运维命令HOCON 作业文件[3],组合 Source、Transform 和 Sink
默认部署✅ 单机 CLI;⚠️ 可借助 Spark Loader 扩展✅ 单机 CLI✅ 单机;✅ 分布式
执行引擎⚠️ 以 CLI 为主,Spark Loader 是独立扩展❌ 不提供 Spark/Flink 执行引擎✅ HugeGraph Source/Sink 支持 Zeta、Spark、Flink[1][2][7][8][9][10]
前端与可观测性❌ 无内置前端,查看 CLI 日志❌ 无内置前端,查看 CLI 日志✅ 内置 Web UI 作业面板,方便查看任务状态和运行情况
输入与输出⚠️ 围绕图导入,支持常见文件、JDBC、Kafka 等⚠️ 围绕图数据和备份文件,支持常见存储✅ 数十种连接器,含 JDBC、Kafka、SQL-CDC 等
调度与资源管理❌ 无统一的跨任务调度和资源分配机制❌ 无统一的跨任务调度和资源分配机制⚠️ 可结合 DolphinScheduler 做调度和任务管理
易用性✅ 专注导入,配置简单;后续提供二进制 CLI 后更方便快速使用✅ 命令直接,适合单机运维⚠️ 配置和运行组件较多,适合长期数据管道
高性能导入✅ 支持 bypass-server 等优化;特定后端和硬件条件下,实测峰值可达 100~200 万条/秒,需按实际场景压测⚠️ 重点是备份和导出,不以批量导入吞吐为主要目标✅ 依靠并行度、分布式引擎和连接器扩展吞吐

SeaTunnel 覆盖 Loader 的图导入和 Tools 的导出、迁移场景,可以把两类任务放进同一条可扩展管道,还支持 SQL-CDC 和数十种输入输出类型。默认情况下,Loader 和 Tools 都在单机运行;SeaTunnel 同时支持单机和分布式部署,可随着数据量和任务数量扩展。Tools 的 schedule-backup 可以创建 crontab 任务,但它不负责统一的任务编排和资源管理。

已有 Spark/Flink 每日任务

HugeGraph Source 和 Sink 在 SeaTunnel 3.0+ 中都支持 SeaTunnel Engine(Zeta)、Spark 和 Flink。若把每日任务改成 SeaTunnel 作业,并用对应引擎提交,数据可以在 Source → Transform → Sink 之间直接传递,不需要先落盘再交给 Loader。若保留现有 Spark/Flink DAG,SeaTunnel 不会自动接管内存中的 DataFrame 或 Stream,需要改造成 SeaTunnel 作业,或让 Source 读取已有系统中的数据

Loader 和 Tools 的优势是专注、直接、上手快。需要直接导入图数据时可先用 Loader;需要备份、恢复、导出或日常运维时可用 Tools。如果已经有 SeaTunnel 作业,通常在原管道中接入 HugeGraph 更方便。需要更高导入吞吐时,Loader 的 bypass-server 和其他导入优化更合适;Loader 在特定后端、数据规模和硬件条件下实测峰值可达 100~200 万条/秒,不能直接当作通用性能承诺,仍需单独压测。新建 SeaTunnel 任务使用 3.0+ 和 mappings。使用其他版本时,请重新核对连接器配置。

2 准备环境

2.1 获取 SeaTunnel 3.0+

使用 JDK 11 并设置 JAVA_HOME;官方部署文档 列出的前置要求为 Java 8 或 11。从官方下载页[4] 选择 3.0+ 二进制发行包,并使用页面提供的校验文件或签名验证下载包。 下面以 3.0.0 为例,请将 SEATUNNEL_VERSION 改为实际下载的发行版本。

1export SEATUNNEL_VERSION=3.0.0
2tar -xzf "apache-seatunnel-${SEATUNNEL_VERSION}-bin.tar.gz"
3cd "apache-seatunnel-${SEATUNNEL_VERSION}"

二进制发行包不包含连接器插件。在 config/plugin_config 中选择示例需要的连接器:

1--seatunnel-connectors--
2connector-hugegraph
3connector-jdbc
4connector-kafka
5--end--

按官方插件安装说明[5] 安装同版本的已发布插件:

1sh bin/install-plugin.sh "${SEATUNNEL_VERSION}"

后续命令均在该安装目录执行,引擎和连接器插件保持相同版本。 本文使用自带的 Zeta 引擎和 local 模式[6][7]。确认 connectors/ 中有 HugeGraph,以及所需的 JDBC 或 Kafka 插件[11][12]。 JDBC 示例还需将 MySQL 驱动 JAR 放入 lib/,驱动类为 com.mysql.cj.jdbc.Driver。

2.2 准备 HugeGraph 和数据源

先启动 HugeGraph Server,创建可用于测试的图。本文示例使用 hugegraph 图、DEFAULT 图空间,请按服务端实际配置修改;图空间名称区分大小写。启用了身份验证时,在 HugeGraph Source 和 Sink 中填写 username、password。

下面的图模型贯穿 JDBC 和 Kafka 示例。mappings 默认会创建缺失的 PropertyKey、VertexLabel 和 EdgeLabel;已有图模型必须与配置兼容。

图元素名称与属性
属性name 为 Text,age 和 since 为 Int
顶点person,主键为 name,属性为 name、age
边knows,从 person 指向 person,属性为 since

所有示例中的 mysql、kafka、hugegraph 都是占位主机名,需替换为 SeaTunnel 运行环境可访问的地址。容器中的 127.0.0.1 指向容器自身;同一 Docker 网络可使用服务名。host 只填主机名或 IP,端口单独填写。

3 从关系库导入(sql2graph)

用两个任务完成导入:先把 person 表写成顶点,再把 knows 表写成边。这样写边时,两个端点都已经存在。

从关系表记录生成顶点和边:person 表映射为顶点,knows 表映射为有向边

3.1 导入顶点

在 MySQL 的 demo 数据库中准备示例数据,并让配置中的账号有读取权限:

1CREATE TABLE person (
2  name VARCHAR(64) PRIMARY KEY,
3  age INT NOT NULL
4);
5INSERT INTO person VALUES ('marko', 29), ('vadas', 27);

保存为 config/sql2graph-person.conf,将数据库账号和密码替换为实际值:

 1env {
 2  job.mode = "BATCH"
 3}
 4
 5source {
 6  Jdbc {
 7    url = "jdbc:mysql://mysql:3306/demo?useSSL=false&serverTimezone=UTC"
 8    driver = "com.mysql.cj.jdbc.Driver"
 9    username = "seatunnel"
10    password = "change_me"
11    query = "SELECT name, age FROM person ORDER BY name"
12  }
13}
14
15sink {
16  HugeGraph {
17    host = "hugegraph"
18    port = 8080
19    graph_name = "hugegraph"
20    graph_space = "DEFAULT"
21    batch_failure_fallback = false
22    mappings = [
23      {
24        type = "VERTEX"
25        label = "person"
26        idStrategy = "PRIMARY_KEY"
27        idFields = ["name"]
28        properties = ["name", "age"]
29      }
30    ]
31  }
32}
1./bin/seatunnel.sh --config ./config/sql2graph-person.conf -m local

在 Hubble 或 Gremlin 中检查结果,应能查到 marko 和 vadas 及其年龄:

1g.V().hasLabel('person').valueMap('name', 'age')

idFields = ["name"] 表示使用名字生成主键。重复导入同一个 name 会写到同一个顶点;properties 指定要写入的源字段。

3.2 导入边

准备关系表,其中两个端点字段对应前面导入的 person.name:

1CREATE TABLE knows (
2  source_name VARCHAR(64) NOT NULL,
3  target_name VARCHAR(64) NOT NULL,
4  since INT NOT NULL
5);
6INSERT INTO knows VALUES ('marko', 'vadas', 2010);
展开配置,保存为 config/sql2graph-knows.conf
 1env {
 2  job.mode = "BATCH"
 3}
 4
 5source {
 6  Jdbc {
 7    url = "jdbc:mysql://mysql:3306/demo?useSSL=false&serverTimezone=UTC"
 8    driver = "com.mysql.cj.jdbc.Driver"
 9    username = "seatunnel"
10    password = "change_me"
11    query = "SELECT source_name, target_name, since FROM knows ORDER BY source_name, target_name"
12  }
13}
14
15sink {
16  HugeGraph {
17    host = "hugegraph"
18    port = 8080
19    graph_name = "hugegraph"
20    graph_space = "DEFAULT"
21    batch_failure_fallback = false
22    check_vertex = true
23    mappings = [
24      {
25        type = "EDGE"
26        label = "knows"
27        sourceConfig = {
28          label = "person"
29          idFields = ["source_name"]
30        }
31        targetConfig = {
32          label = "person"
33          idFields = ["target_name"]
34        }
35        fieldMapping = {
36          source_name = "name"
37          target_name = "name"
38        }
39        properties = ["since"]
40      }
41    ]
42  }
43}

确认顶点任务成功后,再执行边任务:

1./bin/seatunnel.sh --config ./config/sql2graph-knows.conf -m local

下面的查询应返回 marko 到 vadas 的 knows 边,属性 since 为 2010:

1g.V().has('person', 'name', 'marko').outE('knows').where(inV().has('name', 'vadas')).valueMap()

sourceConfig 和 targetConfig 指定端点字段,fieldMapping 将它们对应到顶点主键 name,properties = ["since"] 只写边属性。示例启用 check_vertex = true,并关闭失败后逐条跳过的回退(batch_failure_fallback = false);端点不存在或写入失败时,任务会报错。

如果关系表只有数字外键,而图的主键使用姓名,请先在 SQL 中关联出姓名,再交给 Sink。MySQL CDC 接入方式见 MySQL CDC Source[13]。

4 从 Kafka 导入(kafka2graph)

Kafka 适合持续接收事件。先创建 user-events topic,再写入以下 JSON 消息,每条消息对应一个 person 顶点:

1{"name":"marko","age":29}

保存为 config/kafka2graph.conf:

 1env {
 2  job.mode = "STREAMING"
 3  checkpoint.interval = 10000
 4  sink.flush.interval = 5000
 5}
 6
 7source {
 8  Kafka {
 9    bootstrap.servers = "kafka:9092"
10    topic = "user-events"
11    consumer.group = "hugegraph-import"
12    start_mode = "earliest"
13    format = "json"
14    schema = {
15      fields = {
16        name = "string"
17        age = "int"
18      }
19    }
20  }
21}
22
23sink {
24  HugeGraph {
25    host = "hugegraph"
26    port = 8080
27    graph_name = "hugegraph"
28    graph_space = "DEFAULT"
29    batch_failure_fallback = false
30    mappings = [
31      {
32        type = "VERTEX"
33        label = "person"
34        idStrategy = "PRIMARY_KEY"
35        idFields = ["name"]
36        properties = ["name", "age"]
37      }
38    ]
39  }
40}
1./bin/seatunnel.sh --config ./config/kafka2graph.conf -m local

用第 3.1 节的 Gremlin 查询检查数据。流式任务会持续运行;checkpoint.interval 每 10 秒保存一次任务状态,sink.flush.interval 让 Zeta 每 5 秒触发一次刷新,避免少量消息一直等到批次填满。

HugeGraph Sink 是 at-least-once(至少一次) 写入,故障恢复可能重放记录。使用 PRIMARY_KEY 能让相同 name 落到同一个顶点,但不等于所有更新操作都具备 exactly-once 语义。定时刷新由 Zeta 提供,不适用于 Spark 或 Flink 引擎。

5 常用配置与排错

下表适用于本文使用的 SeaTunnel 3.0+ 版本:

配置用途
host、port分别指定 HugeGraph 主机和端口
graph_name、graph_space选择已创建的图与图空间
mappings定义输入字段如何生成顶点或边
properties每个 mapping 内要写入的源字段列表
schema_save_modemappings 默认自动创建缺失的 Schema;已有 Schema 仍需兼容
batch_size单批记录数,默认 500
env.sink.flush.intervalZeta 定时刷新间隔,单位毫秒
check_vertex写边时检查端点,本文的边任务设为 true
batch_failure_fallback[2]默认 true,批量失败后逐条重试,最多跳过 max_insert_errors 条失败记录;本文示例显式设为 false,让批量失败直接终止任务
max_insert_errors逐条回退时允许跳过的失败记录数;默认 500,-1 表示不限制,仅在开启 batch_failure_fallback 时生效

遇到问题时可按下面检查:

  • 不识别 mappings 或找不到 HugeGraph Source:检查引擎与 HugeGraph connector 是否来自同一次 3.0+ 构建。
  • 连接失败:检查主机、端口、图空间、认证信息,以及 SeaTunnel 所在环境能否访问服务。
  • Schema 不兼容:检查标签的 ID 策略、属性类型和边端点。自动创建不会把已有 PRIMARY_KEY 标签改成 CUSTOMIZE_STRING。
  • Kafka 少量数据未及时出现:确认使用 Zeta,并在 env 中设置 sink.flush.interval。此版本的 batch_interval_ms 仅为兼容保留,不能代替它。

6 选型小结

选工具时,先看要完成的工作:图管理、Gremlin、备份或克隆可用 Tools;直接导入图可先看 Loader;需要复用 Source、Transform、Sink 管道时选 SeaTunnel。使用 SeaTunnel 的图读取和迁移能力时,请按本文使用的 3.0+ 版本准备环境。

按工作流选择工具:图管理用 Tools,直接导入用 Loader,复用数据管道用 SeaTunnel

7 参考文档

HugeGraph 连接器

[1] HugeGraph Source
[2] HugeGraph Sink

配置与部署

[3] HOCON 作业文件配置说明
[4] SeaTunnel 3.0+ 正式版下载
[5] 连接器插件安装说明
[6] SeaTunnel 本地部署

执行引擎

[7] SeaTunnel 引擎概览
[8] SeaTunnel Spark 引擎
[9] SeaTunnel Flink 引擎
[10] Connector V2 多引擎说明

数据源连接器

[11] JDBC Source
[12] Kafka Source
[13] MySQL CDC Source

2.5 - Tools 快速上手

1 HugeGraph-Tools概述

HugeGraph-Tools 提供图与任务管理、备份和恢复命令,也保留旧版 Server/Studio 的部署命令。

测试指南:如需在本地运行 Tools 测试,请参考 工具链本地测试指南

2 获取 HugeGraph-Tools

HugeGraph-Tools 包含在 Toolchain 发布包中,可以下载发布包,也可以从源码编译。

  • 下载二进制tar包
  • 下载源码编译安装

2.1 下载二进制tar包

以下以已发布的 HugeGraph-Toolchain 1.7.0 为例。其他发布版本见下载页。

1export VERSION=1.7.0
2export ARCHIVE="apache-hugegraph-toolchain-incubating-${VERSION}"
3wget "https://downloads.apache.org/hugegraph/${VERSION}/${ARCHIVE}.tar.gz"
4tar zxf "${ARCHIVE}.tar.gz"
5# hugegraph-tools 位于 toolchain 发布包的子目录中,
6# 其版本后缀与发布包本身一致
7cd "${ARCHIVE}/apache-hugegraph-tools-incubating-${VERSION}"

2.2 下载源码编译安装

任选一种方式构建发布版 1.7.0 Tools,开始前先安装 Maven 和 JDK 11。源码包方式还需要 wget。 两段命令均包含编译和进入生成目录,最后用 bin/hugegraph help 查看可用命令。

Git 标签
1git clone --branch 1.7.0 --single-branch https://github.com/apache/hugegraph-toolchain.git
2cd hugegraph-toolchain
3mvn package -pl hugegraph-tools -am -DskipTests -ntp
4cd hugegraph-tools/apache-hugegraph-tools-incubating-1.7.0
5bin/hugegraph help
源码包
1export VERSION=1.7.0
2export ARCHIVE="apache-hugegraph-toolchain-incubating-${VERSION}"
3wget "https://downloads.apache.org/hugegraph/${VERSION}/${ARCHIVE}-src.tar.gz"
4tar zxf "${ARCHIVE}-src.tar.gz"
5cd "${ARCHIVE}-src"
6mvn package -pl hugegraph-tools -am -DskipTests -ntp
7cd "hugegraph-tools/apache-hugegraph-tools-incubating-${VERSION}"
8bin/hugegraph help

编译还会在源码根目录下生成 hugegraph-tools/target/apache-hugegraph-tools-incubating-1.7.0.tar.gz。

2.3 构建当前源码

若需要使用 master 分支未发布的新特性,可按以下步骤从源码构建 Tools(当前 master 以 1.8 为基线,需 JDK 17、Maven 3.6.3+ 与 Python 3.9+):

  1. 获取 Toolchain 源码

    1git clone --branch master --single-branch https://github.com/apache/hugegraph-toolchain.git
    2cd hugegraph-toolchain
  2. 构建配套 Server SDK

    执行以下脚本下载 Server 源码并将配套 SDK 安装到独立 Maven 仓库:

    1java -version
    2mvn -version
    3candidate_dir=$(mktemp -d)
    4mkdir -p "$candidate_dir/m2"
    5bash hugegraph-client/assembly/travis/install-candidate-sdk.sh \
    6  master "$candidate_dir/server" "$candidate_dir/m2"

    详细说明见 Java 17 迁移指引。

  3. 打包 Tools

    1mvn -Dmaven.repo.local="$candidate_dir/m2" \
    2  -Dsdk.validation.mode=candidate \
    3  package -pl hugegraph-tools -am -DskipTests -Dmaven.javadoc.skip=true -ntp
    4cd hugegraph-tools/apache-hugegraph-tools-*
    5bin/hugegraph help

使用这份源码构建时保留 SDK 仓库。master 分支生成目录名不含 incubating。

3 使用

3.1 功能概览

进入解压或编译生成的 Tools 目录,用 bin/hugegraph help 查看命令列表, 用 bin/hugegraph help <子命令> 查看单个命令的用法。可用命令分为以下几类。

  • 图管理类,graph-mode-set、graph-mode-get、graph-list、graph-get、graph-clear、graph-create、graph-clone 和 graph-drop
  • 异步任务管理类,task-list、task-get、task-delete、task-cancel 和 task-clear
  • Gremlin类,gremlin-execute 和 gremlin-schedule
  • 备份/恢复类,backup、restore、migrate、schedule-backup 和 dump
  • 认证数据备份/恢复类,auth-backup 和 auth-restore
  • 旧版 Server/Studio 部署,deploy、clear、start-all 和 stop-all
1Usage: hugegraph [options] [command] [command options]
3.2 [options]-全局变量

以下全局选项可以通过命令行或环境变量设置。

  • --graph 指定要操作的图,默认为 hugegraph。
  • --url 指定 Server 地址,默认为 http://127.0.0.1:8080。
  • --user 在 Server 启用认证时提供用户名。
  • --password 提供该用户的密码。
  • --timeout 设置连接超时时间,默认为 30 秒。
  • --trust-store-file 指定 HTTPS truststore,留空时使用内置的 conf/hugegraph.truststore。
  • --trust-store-password 提供其密码,留空时使用内置 truststore 的密码。
  • --throw-mode 默认为 false,出错时打印错误并退出。设为 true 时抛出异常,主要用于测试。

--url 的 scheme 决定连接协议。使用 https://... 连接 HTTPS 时,才可设置 truststore 选项。 --user 和 --password 必须同时提供或同时省略。

使用 export 设置的环境变量对当前终端及其启动的命令生效。

全局变量环境变量示例
–urlHUGEGRAPH_URLexport HUGEGRAPH_URL=http://127.0.0.1:8080
–graphHUGEGRAPH_GRAPHexport HUGEGRAPH_GRAPH=hugegraph
–userHUGEGRAPH_USERNAMEexport HUGEGRAPH_USERNAME=admin
–passwordHUGEGRAPH_PASSWORDexport HUGEGRAPH_PASSWORD=test
–timeoutHUGEGRAPH_TIMEOUTexport HUGEGRAPH_TIMEOUT=30
–trust-store-fileHUGEGRAPH_TRUST_STORE_FILEexport HUGEGRAPH_TRUST_STORE_FILE=/tmp/trust-store
–trust-store-passwordHUGEGRAPH_TRUST_STORE_PASSWORDexport HUGEGRAPH_TRUST_STORE_PASSWORD=xxxx

下面两种写法查询同一个图的顶点总数,可按使用习惯任选一种。示例使用未启用鉴权的本地 Server;已启用鉴权时还需提供上述用户名和密码。

命令行参数
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph gremlin-execute --script 'g.V().count()'
环境变量
1export HUGEGRAPH_URL=http://127.0.0.1:8080
2export HUGEGRAPH_GRAPH=hugegraph
3./bin/hugegraph gremlin-execute --script 'g.V().count()'

也可以在 bin/hugegraph 脚本中设置这些变量。

 1#!/bin/bash
 2
 3# Set environment here if needed
 4#export HUGEGRAPH_URL=
 5#export HUGEGRAPH_GRAPH=
 6#export HUGEGRAPH_USERNAME=
 7#export HUGEGRAPH_PASSWORD=
 8#export HUGEGRAPH_TIMEOUT=
 9#export HUGEGRAPH_TRUST_STORE_FILE=
10#export HUGEGRAPH_TRUST_STORE_PASSWORD=

bin/hugegraph 还会读取 JAVA_HOME(未设置时打印警告,https 需要它)和 JAVA_OPTIONS(JVM 参数,为空时脚本使用 -Xms512m,并根据机器空闲内存计算 -Xmx)。

3.3 图管理类,graph-mode-set、graph-mode-get、graph-list、graph-get、graph-clear、graph-create、graph-clone和graph-drop
  • graph-mode-set,设置图的 restore mode
    • –graph-mode 或者 -m,必填项,指定将要设置的模式,合法值包括 [NONE, RESTORING, MERGING, LOADING]
  • graph-mode-get,获取图的 restore mode
  • graph-list,列出某个 HugeGraph-Server 中全部的图
  • graph-get,获取某个图及其存储后端类型
  • graph-clear,清除某个图的全部 schema 和 data
    • –confirm-message 或者 -c,必填项,删除确认信息,需要手动输入,二次确认防止误删,“I’m sure to delete all data”,包括双引号
  • graph-create,使用配置文件创建新图
    • –name 或者 -n,选填项,新图的名称,默认为 g
    • –file 或者 -f,图配置文件的路径,文件内容会作为新图的配置发送给 HugeGraph-Server
  • graph-clone,克隆已存在的图
    • –name 或者 -n,选填项,新克隆图的名称,默认为 g
    • –clone-graph-name,选填项,要克隆的源图名称,默认为 hugegraph
  • graph-drop,删除图(不同于 graph-clear,这会完全删除图)
    • –confirm-message 或者 -c,必填项,确认消息 “I’m sure to drop the graph”,包括双引号

graph-create、graph-clone、graph-clear 和 graph-drop 会将 –timeout 提升到至少 300 秒。

当需要把备份的图原样恢复到一个新的图中的时候,需要先将图模式设置为 RESTORING 模式;当需要将备份的图合并到已存在的图中时,需要先将图模式设置为 MERGING 模式。

3.4 异步任务管理类,task-list、task-get、task-delete、task-cancel 和 task-clear
  • task-list,列出某个图中的异步任务,可以根据任务的状态过滤
    • –status,选填项,指定要查看的任务的状态,即按状态过滤任务,合法值包括 [UNKNOWN, NEW, QUEUED, RESTORING, RUNNING, SUCCESS, CANCELLED, FAILED](不区分大小写)
    • –limit,选填项,指定要获取的任务的数目,默认为 -1,意思为获取全部符合条件的任务,显式传入的值必须为正数
  • task-get,获取某个异步任务的详细信息
    • –task-id,必填项,指定异步任务的 ID
  • task-delete,删除某个异步任务的信息
    • –task-id,必填项,指定异步任务的 ID
  • task-cancel,取消某个异步任务的执行
    • –task-id,必填项,要取消的异步任务的 ID
  • task-clear,清理完成的异步任务
    • –force,选填项,设置时,表示清理全部异步任务,未执行完成的先取消,然后清除所有异步任务。默认只清理已完成的异步任务
3.5 Gremlin类,gremlin-execute和gremlin-schedule
  • gremlin-execute,发送 Gremlin 语句到 HugeGraph-Server 来执行查询或修改操作,同步执行,结束后返回结果
    • –file 或者 -f,指定要执行的脚本文件,UTF-8编码,与 –script 互斥
    • –script 或者 -s,指定要执行的脚本字符串,与 –file 互斥
    • –aliases 或者 -a,Gremlin 别名设置,格式为:key1=value1,key2=value2,…
    • –bindings 或者 -b,Gremlin 绑定设置,格式为:key1=value1,key2=value2,…
    • –language 或者 -l,Gremlin 脚本的语言,默认为 gremlin-groovy

    –file 和 –script 二者互斥,必须设置其中之一

  • gremlin-schedule,发送 Gremlin 语句到 HugeGraph-Server 来执行查询或修改操作,异步执行,任务提交后立刻返回异步任务id
    • –file 或者 -f,指定要执行的脚本文件,UTF-8编码,与 –script 互斥
    • –script 或者 -s,指定要执行的脚本字符串,与 –file 互斥
    • –bindings 或者 -b,Gremlin 绑定设置,格式为:key1=value1,key2=value2,…
    • –language 或者 -l,Gremlin 脚本的语言,默认为 gremlin-groovy

    –file 和 –script 二者互斥,必须设置其中之一

3.6 备份/恢复类
  • backup,将某张图中的 schema 或者 data 备份到 HugeGraph 系统之外,以 JSON 形式存在本地磁盘或者 HDFS
    • –format,备份的格式,可选值包括 [json, text],默认为 json
    • –all-properties,是否备份顶点/边全部的属性,仅在 –format 为 text 是有效,默认 false
    • –label,要备份的顶点 label 或者边 label,仅在 –format 为 text 时生效;设置该项时,–huge-types 必须只包含一种类型,且该类型必须是 vertex 或者 edge,否则命令会失败
    • –properties,要备份的顶点/边的属性,逗号分隔,仅在 –format 为 text 是有效,只有备份顶点或者边的时候有效
    • –compress,备份时是否压缩数据,默认为 true
    • –directory 或者 -d,存储 schema 或者 data 的目录,本地目录时,默认为’./{graphName}’,HDFS 时,默认为 ‘{fs.default.name}/{graphName}’
    • –huge-types 或者 -t,要备份的数据类型,逗号分隔,可选值为 ‘all’ 或者 一个或多个 [vertex,edge,vertex_label,edge_label,property_key,index_label] 的组合,‘all’ 代表全部6种类型,即顶点、边和所有schema,‘schema’ 代表 4 种 schema 类型 [vertex_label, edge_label, property_key, index_label]
    • –log 或者 -l,指定日志目录,默认为 ./logs
    • –retry,指定失败重试次数,默认为 3
    • –thread-num 或者 -T,使用的线程数,默认为 Math.min(10, Math.max(4, CPUs / 2))
    • –split-size 或者 -s,指定在备份时对顶点或者边分块的大小,默认为 1048576,且不能小于 1048576(1M)
    • -D,用 -Dkey=value 的模式指定动态参数,用来备份数据到 HDFS 时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000

    当 –timeout 小于 120 秒时,backup(以及 migrate 中的备份步骤)会使用 120 秒

  • restore,将 JSON 格式存储的 schema 或者 data 恢复到一个新图中(RESTORING 模式)或者合并到已存在的图中(MERGING 模式)
    • –directory 或者 -d,存储 schema 或者 data 的目录,本地目录时,默认为’./{graphName}’,HDFS 时,默认为 ‘{fs.default.name}/{graphName}’
    • –clean,是否在恢复图完成后删除 –directory 指定的目录,默认为 false
    • –huge-types 或者 -t,要恢复的数据类型,逗号分隔,可选值为 ‘all’ 或者 一个或多个 [vertex,edge,vertex_label,edge_label,property_key,index_label] 的组合,‘all’ 代表全部6种类型,即顶点、边和所有schema,‘schema’ 代表 4 种 schema 类型 [vertex_label, edge_label, property_key, index_label]
    • –log 或者 -l,指定日志目录,默认为 ./logs
    • –retry,指定失败重试次数,默认为 3
    • –thread-num 或者 -T,使用的线程数,默认为 Math.min(10, Math.max(4, CPUs / 2))
    • -D,用 -Dkey=value 的模式指定动态参数,用来从 HDFS 恢复图时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000

    只有当 –format 为 json 执行 backup 时,才可以使用 restore 命令恢复 restore 要求图处于 RESTORING 或 MERGING 模式(先用 graph-mode-set 设置),否则命令会失败

  • migrate,将当前连接的图迁移至另一个 HugeGraphServer 中
    • –target-graph,目标图的名字,默认为 hugegraph
    • –target-url,目标图所在的 HugeGraphServer,默认为 http://127.0.0.1:8081
    • –target-user,访问目标图的用户名
    • –target-password,访问目标图的密码
    • –target-timeout,访问目标图的超时时间
    • –target-trust-store-file,访问目标图使用的 truststore 文件
    • –target-trust-store-password,访问目标图使用的 truststore 的密码
    • –directory 或者 -d,迁移过程中,存储源图的 schema 或者 data 的目录,本地目录时,默认为’./{graphName}’,HDFS 时,默认为 ‘{fs.default.name}/{graphName}’
    • –huge-types 或者 -t,要迁移的数据类型,逗号分隔,可选值为 ‘all’ 或者 一个或多个 [vertex,edge,vertex_label,edge_label,property_key,index_label] 的组合,‘all’ 代表全部6种类型,即顶点、边和所有schema,‘schema’ 代表 4 种 schema 类型 [vertex_label, edge_label, property_key, index_label]
    • –log 或者 -l,指定日志目录,默认为 ./logs
    • –retry,指定失败重试次数,默认为 3
    • –thread-num 或者 -T,使用的线程数,默认为 Math.min(10, Math.max(4, CPUs / 2))
    • –split-size 或者 -s,指定迁移过程中对源图进行备份时顶点或者边分块的大小,默认为 1048576,且不能小于 1048576(1M)
    • -D,用 -Dkey=value 的模式指定动态参数,用来在迁移图过程中需要备份数据到 HDFS 时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000
    • –graph-mode 或者 -m,将源图恢复到目标图时将目标图设置的模式,合法值包括 [RESTORING, MERGING],默认为 RESTORING。迁移期间目标图会被切换到该模式,迁移结束后恢复为原来的模式
    • –keep-local-data,是否保留在迁移图的过程中产生的源图的备份,默认为 false,即默认迁移图结束后不保留产生的源图备份
  • schedule-backup,周期性对图执行备份操作,并保留一定数目的最新备份(目前仅支持本地文件系统)
    • –directory 或者 -d,必填项,指定备份数据的目录
    • –backup-num,选填项,指定保存的最新的备份的数目,默认为 3
    • –interval,选填项,指定进行备份的周期,格式同 Linux crontab 格式,默认为 “0 0 * * *"(每天 00:00)

    schedule-backup 会添加一条 crontab 任务,定期执行 backup -t all 并写入 {directory}/{graph}/hugegraph-backup-{yyMMddHHmm}/,只保留最新的 –backup-num 份备份。相对路径的 –directory 会相对于 hugegraph-tools 的根目录解析,且 {directory}/{graph} 必须尚不存在

  • dump,把整张图的顶点和边全部导出,默认以 vertex vertex-edge1 vertex-edge2... 的 JSON 格式存储。 用户也可以自定义存储格式。在 hugegraph-tools/src/main/java/org/apache/hugegraph/formatter 下实现一个继承自 Formatter 的类,例如 CustomFormatter,使用时指定该类为 formatter: bin/hugegraph dump -f CustomFormatter
    • –formatter 或者 -f,指定使用的 formatter,默认为 JsonFormatter
    • –directory 或者 -d,存储 schema 或者 data 的目录,本地目录时,默认为’./{graphName}’,HDFS 时,默认为 ‘{fs.default.name}/{graphName}’
    • –log 或者 -l,指定日志目录,默认为 ./logs
    • –retry,指定失败重试次数,默认为 3
    • –thread-num 或者 -T,使用的线程数,默认为 Math.min(10, Math.max(4, CPUs / 2))
    • –split-size 或者 -s,指定在备份时对顶点或者边分块的大小,默认为 1048576,且不能小于 1048576(1M)
    • -D,用 -Dkey=value 的模式指定动态参数,用来备份数据到 HDFS 时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000
3.7 认证数据备份/恢复类
  • auth-backup,备份认证数据到指定目录
    • –types 或者 -t,要备份的认证数据类型,逗号分隔,可选值为 ‘all’ 或者一个或多个 [user, group, target, belong, access] 的组合,‘all’ 代表全部5种类型;包含 ‘belong’ 时必须同时包含 ‘user’ 和 ‘group’,包含 ‘access’ 时必须同时包含 ‘group’ 和 ’target’
    • –directory,备份数据存储目录,本地目录时,默认为 ‘./auth-backup-restore’,HDFS 时,默认为 ‘{fs.default.name}/auth-backup-restore’(该选项没有 -d 短写)
    • –retry,指定失败重试次数,默认为 3
    • -D,用 -Dkey=value 的模式指定动态参数,用来备份数据到 HDFS 时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000
  • auth-restore,从指定目录恢复认证数据
    • –types 或者 -t,要恢复的认证数据类型,逗号分隔,可选值为 ‘all’ 或者一个或多个 [user, group, target, belong, access] 的组合,‘all’ 代表全部5种类型;包含 ‘belong’ 时必须同时包含 ‘user’ 和 ‘group’,包含 ‘access’ 时必须同时包含 ‘group’ 和 ’target’
    • –directory,备份数据存储目录,本地目录时,默认为 ‘./auth-backup-restore’,HDFS 时,默认为 ‘{fs.default.name}/auth-backup-restore’(该选项没有 -d 短写)
    • –retry,指定失败重试次数,默认为 3
    • –strategy,冲突处理策略,可选值为 [stop, ignore],默认为 stop。stop 表示遇到冲突时停止恢复,ignore 表示忽略冲突继续恢复
    • –init-password,恢复用户时设置的初始密码,当 –types 包含 user 时必填
    • -D,用 -Dkey=value 的模式指定动态参数,用来从 HDFS 恢复数据时,指定 HDFS 的配置项,例如:-Dfs.default.name=hdfs://localhost:9000
3.8 安装部署类

注意:此处的安装部署命令仅适用于早期历史版本(Server 0.6.10.10.4 与 Studio 0.6.10.10.0),不支持当前版本的 HugeGraph Server 或 Hubble。 新部署请参考 Server 快速上手 与 Hubble 快速上手, 以下说明仅供维护旧环境参考。

  • deploy,一键下载、安装和启动 HugeGraph-Server 和 HugeGraph-Studio
    • -v,必填项,指定要安装的 HugeGraph-Server 和 HugeGraph-Studio 版本,必须是 bin/version-map.yaml 中列出的版本之一(0.6、0.7、0.8、0.9、0.10),脚本据此映射到对应的 server 和 studio 发布版本
    • -p,必填项,指定安装的 HugeGraph-Server 和 HugeGraph-Studio 目录
    • -u,选填项,指定下载 HugeGraph-Server 和 HugeGraph-Studio 压缩包的链接
  • clear,清理 HugeGraph-Server 和 HugeGraph-Studio 目录和tar包(若对应的 server 或 studio 进程仍在运行则拒绝执行,删除每一项前都会提示确认)
    • -p,必填项,指定要清理的 HugeGraph-Server 和 HugeGraph-Studio 的目录
  • start-all,一键启动 HugeGraph-Server 和 HugeGraph-Studio
    • -v,必填项,指定已安装的 HugeGraph-Server 和 HugeGraph-Studio 版本,取值同 deploy
    • -p,必填项,指定安装了 HugeGraph-Server 和 HugeGraph-Studio 的目录
  • stop-all,一键关闭 HugeGraph-Server 和 HugeGraph-Studio

deploy、start-all、clear 和 stop-all 由 bin/hugegraph 直接转交给 bin/deploy.sh、bin/start-all.sh、bin/clear.sh 和 bin/stop-all.sh 执行,因此 3.2 中的全局变量和环境变量对它们不生效。

deploy命令中有可选参数 -u,提供时会使用指定的下载地址替代默认下载地址下载 tar 包,并且将地址写入~/hugegraph-download-url-prefix文件中;之后如果不指定地址时,会优先从~/hugegraph-download-url-prefix指定的地址下载 tar 包;如果 -u 和~/hugegraph-download-url-prefix都没有时,会从默认下载地址 https://github.com/hugegraph 进行下载

3.9 具体命令参数

各子命令的具体参数如下:

  1Usage: hugegraph [options] [command] [command options]
  2  Options:
  3    --graph
  4      Name of graph
  5      Default: hugegraph
  6    --password
  7      Password of user
  8    --throw-mode
  9      Whether the hugegraph-tools work to throw an exception
 10      Default: false
 11    --timeout
 12      Connection timeout
 13      Default: 30
 14    --trust-store-file
 15      The path of client truststore file used when https protocol is enabled
 16    --trust-store-password
 17      The password of the client truststore file used when the https protocol 
 18      is enabled
 19    --url
 20      The URL of HugeGraph-Server
 21      Default: http://127.0.0.1:8080
 22    --user
 23      Name of user
 24  Commands:
 25    graph-create      Create graph with config
 26      Usage: graph-create [options]
 27        Options:
 28          --file, -f
 29            Creating graph config file
 30          --name, -n
 31            The name of new created graph, default is g
 32            Default: g
 33
 34    graph-clone      Clone graph
 35      Usage: graph-clone [options]
 36        Options:
 37          --clone-graph-name
 38            The name of cloned graph, default is hugegraph
 39            Default: hugegraph
 40          --name, -n
 41            The name of new created graph, default is g
 42            Default: g
 43
 44    graph-list      List all graphs
 45      Usage: graph-list
 46
 47    graph-get      Get graph info
 48      Usage: graph-get
 49
 50    graph-clear      Clear graph schema and data
 51      Usage: graph-clear [options]
 52        Options:
 53        * --confirm-message, -c
 54            Confirm message of graph clear is "I'm sure to delete all data". 
 55            (Note: include "")
 56
 57    graph-drop      Drop graph
 58      Usage: graph-drop [options]
 59        Options:
 60        * --confirm-message, -c
 61            Confirm message of graph clear is "I'm sure to drop the graph". 
 62            (Note: include "")
 63
 64    graph-mode-set      Set graph mode
 65      Usage: graph-mode-set [options]
 66        Options:
 67        * --graph-mode, -m
 68            Graph mode, include: [NONE, RESTORING, MERGING]
 69            Possible Values: [NONE, RESTORING, MERGING, LOADING]
 70
 71    graph-mode-get      Get graph mode
 72      Usage: graph-mode-get
 73
 74    task-list      List tasks
 75      Usage: task-list [options]
 76        Options:
 77          --limit
 78            Limit number, no limit if not provided
 79            Default: -1
 80          --status
 81            Status of task
 82
 83    task-get      Get task info
 84      Usage: task-get [options]
 85        Options:
 86        * --task-id
 87            Task id
 88            Default: 0
 89
 90    task-delete      Delete task
 91      Usage: task-delete [options]
 92        Options:
 93        * --task-id
 94            Task id
 95            Default: 0
 96
 97    task-cancel      Cancel task
 98      Usage: task-cancel [options]
 99        Options:
100        * --task-id
101            Task id
102            Default: 0
103
104    task-clear      Clear completed tasks
105      Usage: task-clear [options]
106        Options:
107          --force
108            Force to clear all tasks, cancel all uncompleted tasks firstly, 
109            and delete all completed tasks
110            Default: false
111
112    gremlin-execute      Execute Gremlin statements
113      Usage: gremlin-execute [options]
114        Options:
115          --aliases, -a
116            Gremlin aliases, valid format is: 'key1=value1,key2=value2...'
117            Default: {}
118          --bindings, -b
119            Gremlin bindings, valid format is: 'key1=value1,key2=value2...'
120            Default: {}
121          --file, -f
122            Gremlin Script file to be executed, UTF-8 encoded, exclusive to 
123            --script 
124          --language, -l
125            Gremlin script language
126            Default: gremlin-groovy
127          --script, -s
128            Gremlin script to be executed, exclusive to --file
129
130    gremlin-schedule      Execute Gremlin statements as asynchronous job
131      Usage: gremlin-schedule [options]
132        Options:
133          --bindings, -b
134            Gremlin bindings, valid format is: 'key1=value1,key2=value2...'
135            Default: {}
136          --file, -f
137            Gremlin Script file to be executed, UTF-8 encoded, exclusive to 
138            --script 
139          --language, -l
140            Gremlin script language
141            Default: gremlin-groovy
142          --script, -s
143            Gremlin script to be executed, exclusive to --file
144
145    backup      Backup graph schema/data. If directory is on HDFS, use -D to 
146            set HDFS params. For example: 
147            -Dfs.default.name=hdfs://localhost:9000 
148      Usage: backup [options]
149        Options:
150          --all-properties
151            All properties to be backup flag
152            Default: false
153          --compress
154            compress flag
155            Default: true
156          --directory, -d
157            Directory of graph schema/data, default is './{graphname}' in 
158            local file system or '{fs.default.name}/{graphname}' in HDFS
159          --format
160            File format, valid is [json, text]
161            Default: json
162          --huge-types, -t
163            Type of schema/data. Concat with ',' if more than one. Other types 
164            include 'all' and 'schema'. 'all' means all vertices, edges and 
165            schema. In other words, 'all' equals with 'vertex, edge, 
166            vertex_label, edge_label, property_key, index_label'. 'schema' 
167            equals with 'vertex_label, edge_label, property_key, index_label'.
168            Default: [PROPERTY_KEY, VERTEX_LABEL, EDGE_LABEL, INDEX_LABEL, VERTEX, EDGE]
169          --label
170            Vertex label or edge label, only valid when type is vertex or edge
171          --log, -l
172            Directory of log
173            Default: ./logs
174          --properties
175            Vertex or edge properties to backup, only valid when type is 
176            vertex or edge
177            Default: []
178          --retry
179            Retry times, default is 3
180            Default: 3
181          --split-size, -s
182            Split size of shard
183            Default: 1048576
184          --thread-num, -T
185            Threads number to use, default is Math.min(10, Math.max(4, CPUs / 
186            2)) 
187            Default: 0
188          -D
189            HDFS config parameters
190            Syntax: -Dkey=value
191            Default: {}
192
193    schedule-backup      Schedule backup task
194      Usage: schedule-backup [options]
195        Options:
196          --backup-num
197            The number of latest backups to keep
198            Default: 3
199        * --directory, -d
200            The directory of backups stored
201          --interval
202            The interval of backup, format is: "a b c d e". 'a' means minute 
203            (0 - 59), 'b' means hour (0 - 23), 'c' means day of month (1 - 
204            31), 'd' means month (1 - 12), 'e' means day of week (0 - 6) 
205            (Sunday=0), "*" means all
206            Default: "0 0 * * *"
207
208    dump      Dump graph to files
209      Usage: dump [options]
210        Options:
211          --directory, -d
212            Directory of graph schema/data, default is './{graphname}' in 
213            local file system or '{fs.default.name}/{graphname}' in HDFS
214          --formatter, -f
215            Formatter to customize format of vertex/edge
216            Default: JsonFormatter
217          --log, -l
218            Directory of log
219            Default: ./logs
220          --retry
221            Retry times, default is 3
222            Default: 3
223          --split-size, -s
224            Split size of shard
225            Default: 1048576
226          --thread-num, -T
227            Threads number to use, default is Math.min(10, Math.max(4, CPUs / 
228            2)) 
229            Default: 0
230          -D
231            HDFS config parameters
232            Syntax: -Dkey=value
233            Default: {}
234
235    restore      Restore graph schema/data. If directory is on HDFS, use -D to 
236            set HDFS params if needed. For 
237            example:-Dfs.default.name=hdfs://localhost:9000 
238      Usage: restore [options]
239        Options:
240          --clean
241            Whether to remove the directory of graph data after restored
242            Default: false
243          --directory, -d
244            Directory of graph schema/data, default is './{graphname}' in 
245            local file system or '{fs.default.name}/{graphname}' in HDFS
246          --huge-types, -t
247            Type of schema/data. Concat with ',' if more than one. Other types 
248            include 'all' and 'schema'. 'all' means all vertices, edges and 
249            schema. In other words, 'all' equals with 'vertex, edge, 
250            vertex_label, edge_label, property_key, index_label'. 'schema' 
251            equals with 'vertex_label, edge_label, property_key, index_label'.
252            Default: [PROPERTY_KEY, VERTEX_LABEL, EDGE_LABEL, INDEX_LABEL, VERTEX, EDGE]
253          --log, -l
254            Directory of log
255            Default: ./logs
256          --retry
257            Retry times, default is 3
258            Default: 3
259          --thread-num, -T
260            Threads number to use, default is Math.min(10, Math.max(4, CPUs / 
261            2)) 
262            Default: 0
263          -D
264            HDFS config parameters
265            Syntax: -Dkey=value
266            Default: {}
267
268    migrate      Migrate graph
269      Usage: migrate [options]
270        Options:
271          --directory, -d
272            Directory of graph schema/data, default is './{graphname}' in 
273            local file system or '{fs.default.name}/{graphname}' in HDFS
274          --graph-mode, -m
275            Mode used when migrating to target graph, include: [RESTORING, 
276            MERGING] 
277            Default: RESTORING
278            Possible Values: [NONE, RESTORING, MERGING, LOADING]
279          --huge-types, -t
280            Type of schema/data. Concat with ',' if more than one. Other types 
281            include 'all' and 'schema'. 'all' means all vertices, edges and 
282            schema. In other words, 'all' equals with 'vertex, edge, 
283            vertex_label, edge_label, property_key, index_label'. 'schema' 
284            equals with 'vertex_label, edge_label, property_key, index_label'.
285            Default: [PROPERTY_KEY, VERTEX_LABEL, EDGE_LABEL, INDEX_LABEL, VERTEX, EDGE]
286          --keep-local-data
287            Whether to keep the local directory of graph data after restored
288            Default: false
289          --log, -l
290            Directory of log
291            Default: ./logs
292          --retry
293            Retry times, default is 3
294            Default: 3
295          --split-size, -s
296            Split size of shard
297            Default: 1048576
298          --target-graph
299            The name of target graph to migrate
300            Default: hugegraph
301          --target-password
302            The password of target graph to migrate
303          --target-timeout
304            The timeout to connect target graph to migrate
305            Default: 0
306          --target-trust-store-file
307            The trust store file of target graph to migrate
308          --target-trust-store-password
309            The trust store password of target graph to migrate
310          --target-url
311            The url of target graph to migrate
312            Default: http://127.0.0.1:8081
313          --target-user
314            The username of target graph to migrate
315          --thread-num, -T
316            Threads number to use, default is Math.min(10, Math.max(4, CPUs / 
317            2)) 
318            Default: 0
319          -D
320            HDFS config parameters
321            Syntax: -Dkey=value
322            Default: {}
323
324    deploy      Install HugeGraph-Server and HugeGraph-Studio
325      Usage: deploy [options]
326        Options:
327        * -p
328            Install path of HugeGraph-Server and HugeGraph-Studio
329          -u
330            Download url prefix path of HugeGraph-Server and HugeGraph-Studio
331        * -v
332            Version of HugeGraph-Server and HugeGraph-Studio
333
334    start-all      Start HugeGraph-Server and HugeGraph-Studio
335      Usage: start-all [options]
336        Options:
337        * -p
338            Install path of HugeGraph-Server and HugeGraph-Studio
339        * -v
340            Version of HugeGraph-Server and HugeGraph-Studio
341
342    clear      Clear HugeGraph-Server and HugeGraph-Studio
343      Usage: clear [options]
344        Options:
345        * -p
346            Install path of HugeGraph-Server and HugeGraph-Studio
347
348    stop-all      Stop HugeGraph-Server and HugeGraph-Studio
349      Usage: stop-all
350
351    auth-backup      null
352      Usage: auth-backup [options]
353        Options:
354          --directory
355            Directory of auth information, default is 
356            './{auth-backup-restore}' in local file system or 
357            '{fs.default.name}/{auth-backup-restore}' in HDFS
358          --retry
359            Retry times, default is 3
360            Default: 3
361          --types, -t
362            Type of auth data to restore and backup, concat with ',' if more 
363            than one. 'all' means all auth information. In other words, 'all' 
364            equals with 'user, group, target, belong, access'. In addition, 
365            'belong' or 'access' can not backup or restore alone, if type 
366            contains 'belong' then should contains 'user' and 'group'. If type 
367            contains 'access' then should contains 'group' and 'target'.
368            Default: [TARGET, GROUP, USER, ACCESS, BELONG]
369          -D
370            HDFS config parameters
371            Syntax: -Dkey=value
372            Default: {}
373
374    auth-restore      null
375      Usage: auth-restore [options]
376        Options:
377          --directory
378            Directory of auth information, default is 
379            './{auth-backup-restore}' in local file system or 
380            '{fs.default.name}/{auth-backup-restore}' in HDFS
381          --init-password
382            Init user password, if restore type include 'user', please specify 
383            the init-password of users.
384            Default: <empty string>
385          --retry
386            Retry times, default is 3
387            Default: 3
388          --strategy
389            The strategy needs to be chosen in the event of a conflict when 
390            restoring. Valid strategies include 'stop' and 'ignore', default 
391            is 'stop'. 'stop' means if there a conflict, stop restore. 
392            'ignore' means if there a conflict, ignore and continue to 
393            restore. 
394            Default: STOP
395            Possible Values: [STOP, IGNORE]
396          --types, -t
397            Type of auth data to restore and backup, concat with ',' if more 
398            than one. 'all' means all auth information. In other words, 'all' 
399            equals with 'user, group, target, belong, access'. In addition, 
400            'belong' or 'access' can not backup or restore alone, if type 
401            contains 'belong' then should contains 'user' and 'group'. If type 
402            contains 'access' then should contains 'group' and 'target'.
403            Default: [TARGET, GROUP, USER, ACCESS, BELONG]
404          -D
405            HDFS config parameters
406            Syntax: -Dkey=value
407            Default: {}
408
409    help      Print usage
410      Usage: help
3.10 具体命令示例
1. gremlin语句
1# 同步执行gremlin
2./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph gremlin-execute --script 'g.V().count()'
3
4# 异步执行gremlin
5./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph gremlin-schedule --script 'g.V().count()'
2. 查看task情况
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph task-list
2
3./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph task-list --limit 5
4
5./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph task-list --status success
3. 图模式查看和设置
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-mode-set -m RESTORING
2
3./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-mode-get
4
5./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-list
4. 清理图
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-clear -c "I'm sure to delete all data"
5. 图备份
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph backup -t all --directory ./backup-test
6. 周期性的备份
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph schedule-backup -d ./backup --interval "*/2 * * * *"
7. 图恢复
1# 设置图模式
2./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-mode-set -m RESTORING
3
4# 恢复图
5./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph restore -t all --directory ./backup-test
6
7# 恢复图模式
8./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph graph-mode-set -m NONE
8. 图迁移
1./bin/hugegraph --url http://127.0.0.1:8080 --graph hugegraph migrate --target-url http://127.0.0.1:8090 --target-graph hugegraph

2.6 - 图导出/迁移

需要备份、导出或在两张图之间迁移数据时,从这里选择工具。Tools 适合单机运维和备份;SeaTunnel Source 适合把图数据接入可扩展的数据管道。

2.6.1 - 使用 SeaTunnel Source 导出与迁移图数据

如果你需要把数据从一张 HugeGraph 图复制到另一张图,使用 graph2graph:HugeGraph Source 从源图(A 图)读取顶点和边,数据经过可选的 Transform 后,由 HugeGraph Sink 写入目标图(B 图)。数据方向是 A 图 → HugeGraph Source →(可选 Transform)→ HugeGraph Sink → B 图。如果要把图数据导出到文件、JDBC、Kafka 等其他系统,则使用 graph2any,由下游 Sink 接收 Source 读取的数据。本文介绍这两类任务。

版本要求:本文面向 SeaTunnel 3.0+

SeaTunnel 3.0+ 提供 HugeGraph Source,支持图模型自动发现和多标签读取。 并行扫描的后端要求和配置限制见官方 Source 文档。

开始前请先完成导入页中的通用环境准备和配置,其中包含 JDK、HOCON、插件安装和图模型说明。

使用 HugeGraph Helm 时,可按 Helm 中的 SeaTunnel 部署说明启动常驻单机或集群, 直接运行挂载的测试作业。跨环境迁移源图的连接地址与认证凭据需按实际环境配置。

1 迁移 HugeGraph 图(graph2graph)

下面从源图迁移 person 顶点和 knows 边。请使用独立的目标图:本节采用 CUSTOMIZE_STRING 保留顶点 ID,不要复用前面已经创建为 PRIMARY_KEY 的 person 标签。

这两个任务只迁移指定标签和属性,不会完整复制源图的索引、TTL 等全部 Schema 配置。运行期间应暂停源图写入,避免两个任务读到不同时间的数据;完成后核对顶点、边数量及抽样属性。

需要保留普通边标签的 Schema ID 和索引定义时,可参考 Helm Chart 中的 Schema 复制及分标签示例。 其中的脚本遇到继承边 PARENT/SUB 会在访问目标图前退出,不会自动迁移继承关系。

跨图迁移示例目录结构

  • helm/hugegraph/examples/seatunnel/clone/
    • copy-schema.py读取源图并写入目标图 Schema(保留 Schema ID 与普通索引)
    • person.conf顶点数据迁移任务配置(CUSTOMIZE_STRING 保留原 ID)
    • knows.conf边数据迁移任务配置(依赖顶点 ID 一致性)
警告

含 DATE 属性时,先确认源 Server 的时区。 SeaTunnel 3.0.0 读取的 REST 日期字符串不带时区, 应在每个 Sink mappings 条目内设置与源 Server 一致的 timeZone,例如 timeZone = "UTC";不要依赖 worker 的默认时区。 Source 的 time_zone 不能修正这些字符串。Chart 的复制示例按源 Server 为 UTC 配置,非 UTC 源需要相应修改,并核对原始时间戳。

跨图迁移时重建主键可能改变顶点 ID;使用 CUSTOMIZE_STRING 保留原 ID,确保边端点匹配

1.1 先迁移顶点

Source 自动补充 ~id 保留列,Sink 把原 ID 作为字符串保存。无需在 schema.fields 中声明 ~id,手动声明保留列会被拒绝。

展开配置,保存为 config/graph2graph-person.conf
 1env {
 2  job.mode = "BATCH"
 3}
 4
 5source {
 6  HugeGraph {
 7    host = "source-hugegraph"
 8    port = 8080
 9    graph_name = "hugegraph"
10    graph_space = "DEFAULT"
11    label = "person"
12    label_type = "VERTEX"
13    schema = {
14      fields = {
15        name = "string"
16        age = "int"
17      }
18    }
19  }
20}
21
22sink {
23  HugeGraph {
24    host = "target-hugegraph"
25    port = 8080
26    graph_name = "hugegraph"
27    graph_space = "DEFAULT"
28    batch_failure_fallback = false
29    mappings = [
30      {
31        type = "VERTEX"
32        label = "person"
33        idStrategy = "CUSTOMIZE_STRING"
34        idFields = ["~id"]
35        properties = ["name", "age"]
36      }
37    ]
38  }
39}
1./bin/seatunnel.sh --config ./config/graph2graph-person.conf -m local

1.2 再迁移边

确认顶点任务成功后,使用 Source 自动补充的 ~source_id 和 ~target_id 定位端点。因为上一任务保留了原 ID,这两列可以直接引用目标图中的顶点。

展开配置,保存为 config/graph2graph-knows.conf
 1env {
 2  job.mode = "BATCH"
 3}
 4
 5source {
 6  HugeGraph {
 7    host = "source-hugegraph"
 8    port = 8080
 9    graph_name = "hugegraph"
10    graph_space = "DEFAULT"
11    label = "knows"
12    label_type = "EDGE"
13    schema = {
14      fields = {
15        since = "int"
16      }
17    }
18  }
19}
20
21sink {
22  HugeGraph {
23    host = "target-hugegraph"
24    port = 8080
25    graph_name = "hugegraph"
26    graph_space = "DEFAULT"
27    check_vertex = true
28    batch_failure_fallback = false
29    mappings = [
30      {
31        type = "EDGE"
32        label = "knows"
33        sourceConfig = {
34          label = "person"
35          idFields = ["~source_id"]
36        }
37        targetConfig = {
38          label = "person"
39          idFields = ["~target_id"]
40        }
41        properties = ["since"]
42      }
43    ]
44  }
45}
1./bin/seatunnel.sh --config ./config/graph2graph-knows.conf -m local

本例打开端点检查,并让写入错误直接导致任务失败。默认的 check_vertex = false 不保证最终一致:缺少端点可能产生悬空边,因此不能用任务成功代替迁移结果检查。

为什么保留 ID? HugeGraph 的 PRIMARY_KEY ID 包含顶点标签的内部 ID,两张图可能不同。例如源图顶点是 1:marko,目标图重新按主键生成的可能是 2:marko。如果重新生成顶点 ID 后仍复用源图的边端点,边就会连错。本例将原 ID 保存为字符串,因此会改变目标图的 ID 策略

若要一次读取全部标签,省略 Source 的 label 后会读取 label_type(默认 VERTEX)下的全部 label,每个 label 输出一张表。这时需用 sourceTable 将各 Sink 映射绑定到对应表,例如 sourceTable = "default.person";具体值以 Writer 日志中的完整表名为准。不能直接套用本节的单标签配置。其他限制见 HugeGraph Source 文档。

2 导出到其他系统(graph2any)

graph2any 使用 HugeGraph Source[1] 读取顶点或边,再交给下游 Sink。下面示例将 person 顶点导出为本地 JSON 文件;导出到 JDBC、Kafka 等系统时,替换 LocalFile[2] 及其配置即可。

 1env {
 2  job.mode = "BATCH"
 3}
 4
 5source {
 6  HugeGraph {
 7    host = "hugegraph"
 8    port = 8080
 9    graph_name = "hugegraph"
10    graph_space = "DEFAULT"
11    label = "person"
12    label_type = "VERTEX"
13    schema = {
14      fields = {
15        name = "string"
16        age = "int"
17      }
18    }
19  }
20}
21
22sink {
23  LocalFile {
24    path = "/tmp/hugegraph-export/${table_name}"
25    file_format_type = "json"
26  }
27}

保存为 config/graph2file-person.conf,在 SeaTunnel 安装目录执行:

1./bin/seatunnel.sh --config ./config/graph2file-person.conf -m local

导出边时,将 Source 的 label 改为边标签、label_type 改为 EDGE,并在 schema.fields 中声明边属性。Source 会额外输出 ~source_id、~source_label、~target_id 和 ~target_label,这些保留列可直接写入文件或交给下游转换步骤。

本页只介绍数据行的读取和写出,不会自动复制源图的索引、TTL 或其他 Schema 设置。完整 Source 参数和通用环境说明请回到SeaTunnel 图导入文档[3]。

3 参考文档

连接器

[1] HugeGraph Source
[2] LocalFile Sink

关联文档

[3] SeaTunnel 图导入文档

2.7 - HugeGraph-Spark-Connector 快速上手

1 HugeGraph-Spark-Connector 概述

HugeGraph-Spark-Connector 使用 Spark DataFrame API 将批量数据写入 HugeGraph。当前实现提供顶点和边的写入器。

目前尚未实现从 HugeGraph 读取数据:表只实现了 SupportsWrite,因此不支持 spark.read.format(...)。连接器支持 CUSTOMIZE 和 PRIMARY_KEY 两种顶点 id 策略,AUTOMATIC 策略会被拒绝。

2 环境要求

  • Java 8+
  • Maven 3.6+
  • Spark 3.2.x(模块基于 Spark 3.2.2 编译,依赖范围为 provided,因此需要由 Spark 运行环境提供 Spark 的 jar)
  • Scala 2.12(基于 Scala 2.12.11 编译)

3 编译

3.1 不执行测试的编译

以下命令均在仓库根目录执行。

1git clone https://github.com/apache/hugegraph-toolchain.git
2cd hugegraph-toolchain
3mvn clean package -pl hugegraph-spark-connector -am -DskipTests -ntp

3.2 执行默认测试的编译

1mvn clean package -pl hugegraph-spark-connector -am -ntp

两条命令都会在 hugegraph-spark-connector/target/hugegraph-spark-connector-${revision}-jar-with-dependencies.jar 生成一个包含依赖的 jar(不包含 Spark 本身)。如果不通过 Maven 管理依赖,可以把它传给 spark-submit --jars。

4 使用方法

先在 pom.xml 中添加依赖,并将 ${revision} 换成实际使用的发布版本:

1<dependency>
2    <groupId>org.apache.hugegraph</groupId>
3    <artifactId>hugegraph-spark-connector</artifactId>
4    <version>${revision}</version>
5</dependency>

format 必须写完整类名 org.apache.hugegraph.spark.connector.DataSource,连接器没有通过 Spark 的 DataSourceRegister 服务注册短名称。当 HugeGraphServer 开启鉴权时,需要在下面的示例中加上 .option("username", ...) 和 .option("token", ...)。

4.1 Schema 定义示例

假设我们有一个图,其 schema 定义如下:

 1schema.propertyKey("name").asText().ifNotExist().create()
 2schema.propertyKey("age").asInt().ifNotExist().create()
 3schema.propertyKey("city").asText().ifNotExist().create()
 4schema.propertyKey("weight").asDouble().ifNotExist().create()
 5schema.propertyKey("lang").asText().ifNotExist().create()
 6schema.propertyKey("date").asText().ifNotExist().create()
 7schema.propertyKey("price").asDouble().ifNotExist().create()
 8
 9schema.vertexLabel("person")
10        .properties("name", "age", "city")
11        .useCustomizeStringId()
12        .nullableKeys("age", "city")
13        .ifNotExist()
14        .create()
15
16schema.vertexLabel("software")
17        .properties("name", "lang", "price")
18        .primaryKeys("name")
19        .ifNotExist()
20        .create()
21
22schema.edgeLabel("knows")
23        .sourceLabel("person")
24        .targetLabel("person")
25        .properties("date", "weight")
26        .ifNotExist()
27        .create()
28
29schema.edgeLabel("created")
30        .sourceLabel("person")
31        .targetLabel("software")
32        .properties("date", "weight")
33        .ifNotExist()
34        .create()

4.2 写入顶点数据(Scala)

 1val df = sparkSession.createDataFrame(Seq(
 2  Tuple3("marko", 29, "Beijing"),
 3  Tuple3("vadas", 27, "HongKong"),
 4  Tuple3("Josh", 32, "Beijing"),
 5  Tuple3("peter", 35, "ShangHai"),
 6  Tuple3("li,nary", 26, "Wu,han"),
 7  Tuple3("Bob", 18, "HangZhou"),
 8)) toDF("name", "age", "city")
 9
10df.show()
11
12df.write
13  .format("org.apache.hugegraph.spark.connector.DataSource")
14  .option("host", "127.0.0.1")
15  .option("port", "8080")
16  .option("graph", "hugegraph")
17  .option("data-type", "vertex")
18  .option("label", "person")
19  .option("id", "name")
20  .option("batch-size", 2)
21  .mode(SaveMode.Overwrite)
22  .save()

4.3 写入边数据(Scala)

 1val df = sparkSession.createDataFrame(Seq(
 2  Tuple4("marko", "vadas", "20160110", 0.5),
 3  Tuple4("peter", "Josh", "20230801", 1.0),
 4  Tuple4("peter", "li,nary", "20130220", 2.0)
 5)).toDF("source", "target", "date", "weight")
 6
 7df.show()
 8
 9df.write
10  .format("org.apache.hugegraph.spark.connector.DataSource")
11  .option("host", "127.0.0.1")
12  .option("port", "8080")
13  .option("graph", "hugegraph")
14  .option("data-type", "edge")
15  .option("label", "knows")
16  .option("source-name", "source")
17  .option("target-name", "target")
18  .option("batch-size", 2)
19  .mode(SaveMode.Overwrite)
20  .save()

4.4 写入 PRIMARY_KEY id 策略的顶点(Scala)

对于使用 primaryKeys(...) 的顶点标签,不要设置 id 选项:id 由主键列拼接生成。不属于 schema 的列可以通过 ignored-fields 丢弃。

 1val df = sparkSession.createDataFrame(Seq(
 2  Tuple4("lop", "java", 328L, "ISBN978-7-107-18618-5"),
 3  Tuple4("ripple", "python", 199L, "ISBN978-7-100-13678-5"),
 4)).toDF("name", "lang", "price", "ISBN")
 5
 6df.write
 7  .format("org.apache.hugegraph.spark.connector.DataSource")
 8  .option("host", "127.0.0.1")
 9  .option("port", "8080")
10  .option("graph", "hugegraph")
11  .option("data-type", "vertex")
12  .option("label", "software")
13  .option("ignored-fields", "ISBN")
14  .option("batch-size", 2)
15  .mode(SaveMode.Overwrite)
16  .save()

4.5 写入两端 id 策略不同的边(Scala)

source-name 和 target-name 各自遵循对应顶点标签的 id 策略。下面的例子中,person 使用自定义字符串 id(一列),software 使用主键(其 name 列):

 1val df = sparkSession.createDataFrame(Seq(
 2  Tuple4("marko", "lop", "20171210", 0.5),
 3  Tuple4("Josh", "lop", "20091111", 0.4),
 4  Tuple4("peter", "ripple", "20171210", 1.0),
 5  Tuple4("vadas", "lop", "20171210", 0.2)
 6)).toDF("source", "name", "date", "weight")
 7
 8df.write
 9  .format("org.apache.hugegraph.spark.connector.DataSource")
10  .option("host", "127.0.0.1")
11  .option("port", "8080")
12  .option("graph", "hugegraph")
13  .option("data-type", "edge")
14  .option("label", "created")
15  .option("source-name", "source") // 自定义 id
16  .option("target-name", "name")   // 主键
17  .option("batch-size", 2)
18  .mode(SaveMode.Overwrite)
19  .save()

关于保存模式:SaveMode.Overwrite 和 SaveMode.Append 都只是插入数据,overwrite 路径不会先删除图中已有的数据。

5 配置参数

选项名匹配时不区分大小写并会去掉首尾空格。data-type 和 label 必填;当 data-type 为 edge 时 source-name 和 target-name 必填;其余选项都有默认值。

5.1 客户端配置

客户端配置用于配置 hugegraph-client。

参数默认值说明
hostlocalhostHugeGraphServer 的地址,可以是主机名或 IP,也可以带 http:// / https:// 前缀
port8080HugeGraphServer 的端口
graphhugegraph图名称
protocolhttp向服务器发送请求的协议,可选 http 或 https
usernamenull当 HugeGraphServer 开启权限认证时,当前图的用户名。未设置时使用图名称作为用户名
tokennull当 HugeGraphServer 开启权限认证时,当前图的 token
timeout60插入结果返回的超时时间(秒)
max-connCPUS * 4HugeClient 与 HugeGraphServer 之间的最大 HTTP 连接数
max-conn-per-routeCPUS * 2HugeClient 与 HugeGraphServer 之间每个路由的最大 HTTP 连接数
trust-store-filenull当请求协议为 https 时,客户端的证书文件路径。https 下未设置时,连接器会读取 JVM 系统属性 connector.home.path 指向目录下的 conf/hugegraph.truststore,此时该属性必须设置
trust-store-tokennull当请求协议为 https 时,客户端的证书密码。https 下未设置时使用 hugegraph

5.2 图数据配置

图数据配置用于说明 DataFrame 如何映射到顶点或边。

参数默认值说明
data-type必填。图数据类型,必须是 vertex 或 edge
label必填。要导入的顶点/边数据所属的标签
id指定某一列作为顶点的 id 列。当顶点 id 策略为 CUSTOMIZE 时,必填;当 id 策略为 PRIMARY_KEY 时,必须为空。不支持 AUTOMATIC id 策略
source-name当 data-type 为 edge 时必填。选择输入源的某些列作为源顶点的 id 列。当源顶点的 id 策略为 CUSTOMIZE 时,必须指定某一列作为顶点的 id 列;当源顶点的 id 策略为 PRIMARY_KEY 时,必须指定一列或多列用于拼接生成顶点的 id,即无论使用哪种 id 策略,此项都是必填的。多列之间用 , 分隔(delimiter 选项对此项不生效)
target-name当 data-type 为 edge 时必填。指定某些列作为目标顶点的 id 列,与 source-name 类似
selected-fields选择某些列进行插入,其他未选择的列不插入,不能与 ignored-fields 同时存在
ignored-fields忽略某些列使其不参与插入,不能与 selected-fields 同时存在
batch-size500导入数据时每批数据的条目数。按 Spark task 生效:每个分区的写入器在缓冲区累积到该数量的顶点/边时向服务端提交一次,commit 时再提交剩余部分

5.3 通用配置

通用配置包含一些常用的配置项。

参数默认值说明
delimiter,selected-fields 和 ignored-fields 的分隔符。source-name 和 target-name 始终按 , 拆分

6 注意事项与限制

  • 每个 Spark 写入 task 会创建自己的 HugeClient,写入前把图切换到 LOADING 模式,commit 或 abort 时恢复为 NONE 模式。
  • 顶点 id 长度限制为 128 字节(UTF-8),对自定义字符串 id 和由主键拼接出的 id 都生效。
  • 不支持 AUTOMATIC 顶点 id 策略,创建写入器时会抛出 IllegalArgumentException,写入失败。
  • 暂不支持 SET 或 LIST 基数的属性,只会转换 SINGLE 基数的值。
  • 日期属性:字符串值必须使用 yyyy-MM-dd HH:mm:ss 格式,按 GMT+8 时区解析;数值会被当作毫秒时间戳。
  • 以字符串形式给出的布尔属性接受 true、1、yes、y 和 false、0、no、n(不区分大小写)。
  • 自定义字符串 id 或任一主键值为空字符串的行会被跳过;为 null 时则会报错。

7 许可证

与 HugeGraph 一样,hugegraph-spark-connector 也采用 Apache 2.0 许可证。

3 - HugeGraph-AI

hugegraph-ai 提供 HugeGraph 的 Python 客户端、图机器学习工具,以及面向知识图谱构建和 GraphRAG 的 LLM 工具。

Apache License 2.0 · Ask DeepWiki

模块

仓库使用 uv workspace,其成员是 hugegraph-llm 和 hugegraph-python-client。hugegraph-ml 和 vermeer-python-client 是可编辑的路径依赖,不在 workspace members 中。当前仓库版本为 1.7.0。客户端源码目录叫 hugegraph-python-client,但发行包名是 hugegraph-python。

环境要求

  • HugeGraph-AI 根目录 workspace:Python 3.10 或更高版本;HugeGraph-LLM 还要求低于 3.12
  • HugeGraph-ML:Python 3.10 或更高版本
  • PyPI 上的 hugegraph-python 1.5.0:Python 3.9 或更高版本;当前仓库源码随 workspace 使用 Python 3.10 或更高版本
  • Vermeer Python 客户端:当前源码要求 Python 3.10 或更高版本;发行元数据仍声明 >=3.9,详见客户端页
  • uv 0.7 或更高版本
  • HugeGraph Server 1.5.0 或更高版本;当前 workspace 的 Python 客户端会拒绝可探测到的更低版本

可选依赖组

根项目为每个模块声明一个 extra,另有几个组合项:

Extra安装内容
llmhugegraph-llm
mlhugegraph-ml
python-clienthugegraph-python(源码目录 hugegraph-python-client)
vermeervermeer-python-client
devpytest、pytest-cov、coverage、pylint、ruff、mypy、ty、pre-commit
nk-llmhugegraph-llm、hugegraph-python-client,以及编译镜像所需的 Nuitka
all四个模块包

hugegraph-llm 自身还声明了 vectordb extra,用于安装 pymilvus 和 qdrant-client。

Docker Compose 部署

仓库提供同时启动 HugeGraph Server 和 RAG 服务的 Compose 文件:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3cp docker/env.template docker/.env
4# 编辑 docker/.env,将 PROJECT_PATH 改为当前仓库的绝对路径
5touch hugegraph-llm/.env
6# 在 hugegraph-llm/.env 中设置 GRAPH_URL=server:8080,并填写匹配 Server 的账号
7cd docker
8docker compose -f docker-compose-network.yml up -d

默认地址:

  • HugeGraph Server:http://localhost:8080
  • RAG 服务和 Web 界面:http://localhost:8001

从源码启动 RAG 服务

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra llm
4source .venv/bin/activate
5cd hugegraph-llm
6python -m hugegraph_llm.demo.rag_demo.app

uv sync 会在仓库根目录创建 .venv。从根目录安装可让 uv 一起解析 workspace 成员和路径依赖。当前仓库不跟踪 uv.lock;uv sync 会按 pyproject.toml 中的依赖声明和版本约束解析依赖。

安装 ML 依赖

1cd hugegraph-ai
2uv sync --extra ml
3source .venv/bin/activate
4cd hugegraph-ml/src

示例脚本位于 hugegraph-ml/src/hugegraph_ml/examples/。

后续阅读

3.1 - HugeGraph-LLM

HugeGraph-LLM 用于知识图谱构建、GraphRAG 和自然语言图查询。演示服务把 Gradio 页面和 FastAPI 接口挂在同一个进程上,直接从源码启动时默认只监听本机 127.0.0.1:8001,可用 http://localhost:8001 访问。若显式启动源码入口且只需本机访问,可指定 --host 127.0.0.1;源码 Docker 镜像的 Dockerfile.llm 会覆盖默认值并监听 0.0.0.0:8001,不要在容器内改为 loopback,否则容器外无法通过映射端口访问。

警告

生产环境必须为 HugeGraph-LLM 启用自身的登录认证(ENABLE_LOGIN=True,并替换 USER_TOKEN、ADMIN_TOKEN),同时在防火墙或网络入口设置来源 IP 白名单。HugeGraph Server 还必须单独开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 GRAPH_USER 配置只具备该服务所需权限的账号。AI 服务 token 只认证 LLM 页面和 API,不能替代 HugeGraph Server 认证。

环境要求

AI 总结项目文档:Ask DeepWiki

  • Python 3.10 或 3.11(>=3.10,<3.12)
  • uv 0.7 或更高版本
  • HugeGraph Server 1.5.0 或更高版本;当前 workspace 中的 Python 客户端会拒绝可探测到的更低版本

Docker Compose 部署

在 HugeGraph-AI 仓库根目录准备环境文件:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3cp docker/env.template docker/.env
4# 编辑 docker/.env,将 PROJECT_PATH 改为当前仓库的绝对路径
5touch hugegraph-llm/.env
6# 编辑 hugegraph-llm/.env:GRAPH_URL=server:8080,并设置与 Server 相符的 GRAPH_USER、GRAPH_PWD
7cd docker
8docker compose -f docker-compose-network.yml up -d
9docker compose -f docker-compose-network.yml ps

启动后可访问:

  • HugeGraph Server:http://localhost:8080
  • RAG 服务和 Web 页面:http://localhost:8001

Compose 文件会把 ${PROJECT_PATH}/hugegraph-llm/.env 挂载到容器内的 /home/work/hugegraph-llm/.env,因此该文件必须在容器启动前存在。资源目录 hugegraph-llm/src/hugegraph_llm/resources 也可以用同样方式挂载,该挂载默认被注释掉。

应用读取 GRAPH_URL,Compose 注入的 HUGEGRAPH_HOST 和 HUGEGRAPH_PORT 不会覆盖它;因此容器内要将 GRAPH_URL 设为 server:8080,并在 .env 中配置匹配 HugeGraph Server 的用户名和密码。

容器镜像

镜像构建文件内容
docker/Dockerfile.llm源码运行镜像构建配方,入口是 python -m hugegraph_llm.demo.rag_demo.app --host 0.0.0.0 --port 8001
docker/Dockerfile.nk基于 nk-llm extra 用 Nuitka 编译的二进制镜像构建配方,入口是 ./app.dist/app.bin

Compose 文件引用未指定标签的 hugegraph/rag,Docker 会使用默认的 latest 标签。scripts/build_llm_image.sh 则以 docker/Dockerfile.llm 在本地构建 hugegraph/graphrag:1.7.0。Compose 引用的 hugegraph/rag:latest 与本地构建的 hugegraph/graphrag:1.7.0 是不同镜像;本地构建不会自动替换 Compose 所用镜像。要在 Compose 中运行本地构建结果,需将 Compose 的 image 改为 hugegraph/graphrag:1.7.0。该脚本只构建镜像,不会推送。两个 Dockerfile 都声明 8001 端口、以非 root 用户 work 运行,并用 curl -f http://localhost:8001/ 做镜像健康检查;两者都为资源目录声明数据卷。

scripts/build_llm_image.sh 会用 docker/Dockerfile.llm 构建并打上 hugegraph/graphrag:1.7.0 标签。

Kubernetes 部署

docker/charts/hg-llm 是 RAG 服务的 Helm chart,部署 hugegraph/graphrag 镜像。默认发布 NodePort 类型的 Service,把节点端口 8039 和服务端口 8080 映射到容器端口 8001,名称固定为 hg-llm-service。Ingress 和水平自动扩缩容已定义但默认关闭。

该 chart 只部署 RAG 服务,不会部署 HugeGraph Server。挂载的 .env 中要把 GRAPH_URL 设为 Pod 可访问的 HugeGraph 地址,并配置匹配的用户名和密码。

chart 中 image.tag 仍默认为 v0.0.1。当前构建脚本生成的标签是本地 hugegraph/graphrag:1.7.0;部署前须确保同名镜像已推送到集群可访问的仓库,或已加载到集群节点,并将 chart 的标签和拉取策略设为匹配的值。

chart 的 values.yaml 中,.env 和提示词 YAML 的挂载默认被注释掉。提示词 YAML 可用 ConfigMap;.env 可能含有密钥和密码,应使用 Secret,并把 volumes 中 env-config 的 configMap 改为 secret。Secret 和提示词 ConfigMap 可分别创建:

1kubectl create secret generic hugegraph-llm-env --from-file=.env=/path/to/.env
2kubectl create configmap hugegraph-llm-prompt-config --from-file=/path/to/config_prompt.yaml

随后取消 volumeMounts 段落的注释,并按需要启用提示词 ConfigMap 的 volumes 和挂载。Helm 模板会直接渲染 values.yaml 中的卷定义。

从源码启动

依赖应从仓库根目录按 workspace 安装:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra llm
4source .venv/bin/activate
5cd hugegraph-llm
6python -m hugegraph_llm.demo.rag_demo.app

自定义监听地址和端口:

1python -m hugegraph_llm.demo.rag_demo.app \
2  --host 127.0.0.1 \
3  --port 18001

设置 HG_DEV_RELOAD=1 可让 uvicorn 以自动重载方式启动,便于开发调试。

服务以 hugegraph-llm/.env 保存模型、HugeGraph 和登录配置。提示词放在 hugegraph-llm/src/hugegraph_llm/resources/demo/config_prompt.yaml。缺少文件时,配置代码会按默认值创建。

.env 路径按以下顺序解析:先看是否设置了 HUGEGRAPH_LLM_ENV_PATH;未设置时,从源码运行则使用 hugegraph-llm/.env;否则使用当前工作目录下的 .env。

主要功能

构建 RAG 索引

Web 页面的第一个标签页可以处理文本或文件,并执行以下操作:

  1. 切分文本并写入 chunk 向量索引。
  2. 按给定 Schema 从文本抽取顶点和边。
  3. 将抽取结果写入 HugeGraph,并更新顶点向量索引。

文本可以在 text 子页直接输入,也可以在 file 子页上传。上传支持 .txt、.docx 和 .pdf,并可一次选择多个文件。加密 PDF 以及没有可提取文本层的扫描件 PDF 会被拒绝。

Schema 可以是内联 JSON,也可以是现有图名。通过 REST API 使用图名时,必须同时传入匹配的 client_config.graph;内联 JSON 不会连接 HugeGraph,也不能附带 client_config。

该标签页还提供两个生成器。Graph Schema Generator 根据查询示例和少样本示例生成 Schema。Graph Extraction Prompt Generator 根据描述的场景和选定的参考示例生成抽取提示词。Graph Extraction Split Type 下拉框可在抽取前选择 document、paragraph 或 sentence 粒度。

GraphRAG

查询流程可以组合直接回答、chunk 向量召回和图召回。图召回先抽取关键词并匹配顶点,再尝试 Text2Gremlin;生成或执行失败时可回退到预定义的图遍历方式。请求参数可控制返回数量、向量距离阈值、模板数量和重排序方式。

同一标签页还有批量回归测试面板,可从 .xlsx 或 .csv 文件读取问题、逐条作答,并返回可下载的结果文件。上传控件旁提供模板文件下载。

知识图谱构建器

Text2Gremlin

POST /text2gremlin 根据自然语言、图 Schema 和可选示例生成 Gremlin。自定义提示词必须保留 {query}、{schema}、{example} 和 {vertices} 四个占位符。

对应的页面标签可以先用问题与 Gremlin 对照文件(.json 或 .csv)构建示例向量索引。未上传文件时使用内置的 resources/demo/text2gremlin.csv。

图工具与管理工具

Graph Tools 标签页可直接执行 Gremlin 查询、手动触发图备份,以及初始化 HugeGraph 演示数据。Admin Tools 标签页在校验 ADMIN_TOKEN 后展示 logs/llm-server.log 的末尾内容,并可刷新或清空该文件。

进程运行期间还有两个后台任务:每天 01:00 执行图备份的定时任务,以及持续更新顶点 id 向量的任务。

模型与向量后端

聊天、信息抽取和 Text2Gremlin 可以分别使用 OpenAI 兼容接口、Ollama 或 LiteLLM。嵌入模型可独立选择,同样支持这三种提供方。重排序支持 Cohere 和 SiliconFlow。

默认向量索引使用 FAISS。CUR_VECTOR_INDEX 可选 Faiss、Milvus 或 Qdrant,Web 页面的 5. Set up the vector engine. 面板提供同样的选择。Milvus 和 Qdrant 需要安装可选依赖:

1cd hugegraph-ai
2uv sync --package hugegraph-llm --extra vectordb

页面操作流程见使用流程,完整环境变量见配置参考,HTTP 请求格式见REST API。

程序化调用

原有的 RAGPipeline 和 KgBuilder 类已被流水线调度器取代。通过 SchedulerSingleton 按名称调用流程:

 1from hugegraph_llm.flows.scheduler import SchedulerSingleton
 2
 3scheduler = SchedulerSingleton.get_instance()
 4res = scheduler.schedule_flow(
 5    "rag_graph_only",
 6    query="Tell me about Al Pacino.",
 7    graph_only_answer=True,
 8    vector_only_answer=False,
 9    raw_answer=False,
10    gremlin_tmpl_num=-1,
11    gremlin_prompt=None,
12)
13print(res.get("graph_only_answer"))

已注册的流程名包括 rag_raw、rag_vector_only、rag_graph_only、rag_graph_vector、text2gremlin、build_examples_index、build_vector_index、graph_extract、import_graph_data、update_vid_embeddings、get_graph_index_info、build_schema 和 prompt_generate。schedule_stream_flow 是对应的异步流式版本。

开发检查

先在仓库根目录安装模块和开发工具,再运行与 CI 一致的检查:

 1cd hugegraph-ai
 2uv sync --extra llm --extra dev
 3uv run ruff format --check .
 4uv run ruff check .
 5
 6cd hugegraph-llm
 7SKIP_EXTERNAL_SERVICES=true uv run pytest src/tests/config/ src/tests/document/ src/tests/middleware/ \
 8  src/tests/operators/ src/tests/models/ src/tests/indices/ src/tests/test_utils.py -v --tb=short
 9SKIP_EXTERNAL_SERVICES=true uv run pytest src/tests/integration/test_graph_rag_pipeline.py \
10  src/tests/integration/test_kg_construction.py src/tests/integration/test_rag_pipeline.py -v --tb=short

Git hook 通过 pre-commit 启用:

1cd hugegraph-ai
2pre-commit install
3pre-commit run --all-files

3.2 - HugeGraph-ML

HugeGraph-ML 从 HugeGraph 读取图数据并转换为 DGL 图,供节点嵌入、节点分类、图分类、链接预测和欺诈检测等任务使用。模型实现位于 hugegraph-ml/src/hugegraph_ml/models/。

环境要求

  • Python 3.10 或更高版本
  • HugeGraph Server 1.5.0 或更高版本;当前 workspace 中的 Python 客户端会拒绝可探测到的更低版本
  • uv 0.7 或更高版本

所有服务端访问都通过同一仓库中的 hugegraph-python-client(即 pyhugegraph 包)完成。HugeGraph2DGL 使用 Gremlin 接口的 g.V().hasLabel(...) 和 g.E().hasLabel(...) 拉取点边,数据集导入函数则通过 schema 接口和顶点、边的批量接口写入,每批 500 条。

ML 依赖在仓库根目录的 [tool.uv] constraint-dependencies 中声明版本约束:

依赖版本约束
torch==2.2.0
dgl~=2.1.0
ogb~=1.3.6
torchdata~=0.7.0
catboost~=1.2.3
category-encoders~=2.6.3
numpy~=1.24.4
pandas~=2.2.3

这些约束限定依赖版本,不指定 CPU 或 CUDA 构建。支持 gpu 参数的任务默认值 -1 表示使用 CPU;使用 GPU 时,需要安装彼此兼容的 CUDA 版 torch 和 dgl。

安装

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra ml
4source .venv/bin/activate
5cd hugegraph-ml/src

HugeGraph-ML 是根项目的路径依赖,但不属于 uv workspace members。应在仓库根目录选择 ml extra,让 uv 按 workspace 配置安装它及其本地客户端依赖。

已实现模型

下列模块均位于 hugegraph-ml/src/hugegraph_ml/models/。models/__init__.py 不做任何再导出,需要直接从模块文件导入。

模型模块入口类用途论文
AGNNagnn.pyAGNN节点分类1803.03735
APPNPappnp.pyAPPNP节点分类1810.05997
ARMAarma.pyARMA4NC节点分类1901.01343
BGNNbgnn.pyBGNNPredictor梯度提升与 GNN 结合处理节点特征,自带示例执行回归任务2101.08543
BGRLbgrl.pyBGRL自监督节点嵌入2102.06514
CARE-GNNcare_gnn.pyCAREGNN欺诈检测2008.08692
Cluster-GCNcluster_gcn.pySAGE基于子图采样的节点分类1905.07953
C&Scorrect_and_smooth.pyMLP、CorrectAndSmooth、LabelPropagation对基础预测结果做校正与平滑2010.13993
DAGNNdagnn.pyDAGNN节点分类2007.09296
DeeperGCNdeepergcn.pyDeeperGCN带边特征的节点分类2006.07739
DGIdgi.pyDGI自监督节点嵌入1809.10341
DiffPooldiffpool.pyDiffPool图分类1806.08804
GATNEgatne.pyDGLGATNE异构网络嵌入1905.01669
GINgin_global_pool.pyGIN图分类
GRACEgrace.pyGRACE自监督节点嵌入2006.04131
GRANDgrand.pyGRAND节点分类2005.11079
JKNetjknet.pyJKNet节点分类1806.03536
MLPmlp.pyMLPClassifier基于已学习嵌入的下游分类器
P-GNNpgnn.pyPGNN链接预测you19b
SEALseal.pyDGCNN、SEALData链接预测1802.09691

GIN 的 pooling 参数可取 sum(默认)、mean、max、global_attention 和 set2set。

读取图数据

hugegraph-ml/src/hugegraph_ml/data/hugegraph2dgl.py 中的 HugeGraph2DGL 会创建 PyHugeClient,并把查询结果转换为 DGL 对象:

1from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
2
3hg2d = HugeGraph2DGL(
4    url="http://127.0.0.1:8080",
5    graph="hugegraph",
6    user="",
7    pwd="",
8    graphspace=None,
9)
方法返回值说明
convert_graph(vertex_label, edge_label, feat_key="feat", label_key="label", mask_keys=None)dgl.DGLGraphmask_keys 为空时取 ["train_mask", "val_mask", "test_mask"]
convert_hetero_graph(vertex_labels, edge_labels, feat_key="feat", label_key="label", mask_keys=None)DGL 异构图参数为标签列表
convert_graph_dataset(graph_vertex_label, vertex_label, edge_label, feat_key="feat", label_key="label")HugeGraphDatasetinfo 中写入 n_graphs、max_n_nodes、n_feat_dim、n_classes
convert_graph_nx(vertex_label, edge_label)networkx.GraphP-GNN 使用
convert_graph_with_edge_feat(vertex_label, edge_label, node_feat_key="feat", edge_feat_key="edge_feat", label_key="label", mask_keys=None)dgl.DGLGraph同时填充 edata["feat"]
convert_graph_ogb(vertex_label, edge_label, split_label)(dgl.DGLGraph, split_edge)SEAL 使用
convert_hetero_graph_bgnn(vertex_labels, edge_labels, feat_key="feat", label_key="class", cat_key="cat_features", mask_keys=None)DGL 异构图BGNN 使用

节点特征写入 ndata["feat"],标签写入 ndata["label"],各掩码写入 ndata[<mask key>]。NodeEmbed 只要求 feat;NodeClassify、NodeClassifyWithEdge 和 NodeClassifyWithSample 要求 feat、label、train_mask、val_mask 和 test_mask,缺少任意一项都会抛出 ValueError。

导入示例数据集

hugegraph_ml.utils.dgl2hugegraph_utils 负责把 DGL、OGB 和 NetworkX 数据集写入 HugeGraph,供转换层读取。这些函数都接受与 HugeGraph2DGL 相同的 url、graph、user、pwd 和 graphspace 参数,并且多数会先把数据集名转为大写再匹配。

函数支持的数据集创建的标签
import_graph_from_dglCORA、CITESEER、PUBMED<NAME>_vertex、<NAME>_edge
import_graphs_from_dglMUTAG、COLLAB、NCI1、PROTEINS、PTC、ENZYMES、DD<NAME>_graph_vertex、<NAME>_vertex、<NAME>_edge
import_hetero_graph_from_dglACM<NAME>_<ntype>_v、<NAME>_<etype>_e
import_hetero_graph_from_dgl_no_featAMAZONGATNE<NAME>_<ntype>_v、<NAME>_<etype>_e
import_hetero_graph_from_dgl_bgnnAVAZU<NAME>_<ntype>_v、<NAME>_<etype>_e
import_graph_from_nxCAVEMAN<NAME>_vertex、<NAME>_edge
import_graph_from_dgl_with_edge_featCORA、CITESEER、PUBMED<NAME>_edge_feat_vertex、<NAME>_edge_feat_edge
import_graph_from_ogbogbl-collab,不做大写转换<NAME>_vertex、<NAME>_edge
import_split_edge_from_ogbogbl-collab,不做大写转换<NAME>_split_edge

传入其他名称会抛出 ValueError("dataset not supported")。import_split_edge_from_ogb 还需要顶点导入返回的 idx_to_vertex_id 映射和 max_nodes 上限。

clear_all_data() 会清空目标图中的全部点和边。测试 fixture 先调用它,再导入 CORA、MUTAG 和 ACM,结束时再次调用。

AMAZONGATNE 和 AVAZU 不会自动下载,压缩包地址写在 import_hetero_graph_from_dgl_no_feat 和 import_hetero_graph_from_dgl_bgnn 上方的注释里。

任务

任务类位于 hugegraph-ml/src/hugegraph_ml/tasks/,均接收转换后的图和模型实例。

类模块入口方法
NodeEmbednode_embed.pytrain_and_embed(add_self_loop=True, lr=1e-3, weight_decay=0, n_epochs=200, patience=inf, gpu=-1),返回 ndata["feat"] 被替换为嵌入结果的图
NodeClassifynode_classify.py先 train(lr, weight_decay, n_epochs, patience, early_stopping_monitor, gpu),再 evaluate() 返回 {"accuracy": ..., "loss": ...}
NodeClassifyWithEdgenode_classify_with_edge.py结构相同,适用于同时读取 edata["feat"] 的模型
NodeClassifyWithSamplenode_classify_with_sample.py基于 ClusterGCNSampler 分区的训练,仅使用 CPU,没有 gpu 参数
GraphClassifygraph_classify.pytrain(batch_size=20, lr, weight_decay, n_epochs, patience, early_stopping_monitor, clip=2.0, gpu),在 HugeGraphDataset 上按 70/20/10 划分
DetectorCaregnnfraud_detector_caregnn.pyCARE-GNN 训练,evaluate() 输出 recall 和 ROC AUC,并读取 ndata["feature"] 而非 ndata["feat"]
HeteroSampleEmbedGATNEhetero_sample_embed_gatne.pytrain_and_embed(lr=1e-3, n_epochs=200, gpu=-1)
LinkPredictionPGNNlink_prediction_pgnn.pytrain(lr, weight_decay, n_epochs, gpu)
LinkPredictionSeallink_prediction_seal.py构造函数内部已调用 data_prepare(),随后执行 train(lr=1e-3, n_epochs=200, gpu=-1)

patience 默认值为 float("inf")。utils/early_stopping.py 中的 EarlyStopping 可以监控 loss 或 accuracy,保存最优权重并在训练结束时恢复。

可运行示例

脚本位于 hugegraph-ml/src/hugegraph_ml/examples/。在 hugegraph-ml/src 目录下执行:

1python ./hugegraph_ml/examples/dgi_example.py

每个脚本同时提供同名函数,可以导入后用较小的 epoch 数调用。

脚本模型任务读取的标签
agnn_example.pyAGNNNodeClassifyCORA_vertex、CORA_edge
appnp_example.pyAPPNPNodeClassifyCORA_vertex、CORA_edge
arma_example.pyARMA4NCNodeClassifyCORA_vertex、CORA_edge
bgnn_example.pyBGNNPredictor模型自带的 fit()AVAZU__N_v、AVAZU__E_e
bgrl_example.pyBGRLNodeEmbed、NodeClassifyCORA_vertex、CORA_edge
care_gnn_example.pyCAREGNNDetectorCaregnnAMAZON_user_v 以及 AMAZON_net_upu_e、AMAZON_net_usu_e、AMAZON_net_uvu_e
cluster_gcn_example.pySAGENodeClassifyWithSampleCORA_vertex、CORA_edge
correct_and_smooth_example.pycorrect_and_smooth 中的 MLPNodeClassifyCORA_vertex、CORA_edge
dagnn_example.pyDAGNNNodeClassifyCORA_vertex、CORA_edge
deepergcn_example.pyDeeperGCNNodeClassifyWithEdge通过 convert_graph_with_edge_feat 读取 CORA_vertex、CORA_edge
dgi_example.pyDGINodeEmbed、NodeClassifyCORA_vertex、CORA_edge
diffpool_example.pyDiffPoolGraphClassifyMUTAG_graph_vertex、MUTAG_vertex、MUTAG_edge
gatne_example.pyDGLGATNEHeteroSampleEmbedGATNEAMAZONGATNE__N_v、AMAZONGATNE_1_e、AMAZONGATNE_2_e
gin_example.pyGINGraphClassifyMUTAG_graph_vertex、MUTAG_vertex、MUTAG_edge
grace_example.pyGRACENodeEmbed、NodeClassifyCORA_vertex、CORA_edge
grand_example.pyGRANDNodeClassifyCORA_vertex、CORA_edge
jknet_example.pyJKNetNodeClassifyCORA_vertex、CORA_edge
pgnn_example.pyPGNNLinkPredictionPGNNCAVEMAN_vertex、CAVEMAN_edge
seal_example.pyDGCNNLinkPredictionSealogbl-collab_vertex、ogbl-collab_edge、ogbl-collab_split_edge

DGI 节点嵌入示例

先把 DGL 的 Cora 数据集导入 HugeGraph。数据集名会先转为大写,因此 cora 和 CORA 都会生成 CORA_vertex 和 CORA_edge 标签:

1from hugegraph_ml.utils.dgl2hugegraph_utils import import_graph_from_dgl
2
3import_graph_from_dgl("cora")

读取图并训练 DGI:

 1from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
 2from hugegraph_ml.models.dgi import DGI
 3from hugegraph_ml.models.mlp import MLPClassifier
 4from hugegraph_ml.tasks.node_classify import NodeClassify
 5from hugegraph_ml.tasks.node_embed import NodeEmbed
 6
 7hg2d = HugeGraph2DGL()
 8graph = hg2d.convert_graph(
 9    vertex_label="CORA_vertex",
10    edge_label="CORA_edge",
11)
12
13embed_model = DGI(n_in_feats=graph.ndata["feat"].shape[1])
14embed_task = NodeEmbed(graph=graph, model=embed_model)
15embedded_graph = embed_task.train_and_embed(
16    add_self_loop=True,
17    n_epochs=300,
18    patience=30,
19)
20
21classifier = MLPClassifier(
22    n_in_feat=embedded_graph.ndata["feat"].shape[1],
23    n_out_feat=embedded_graph.ndata["label"].unique().shape[0],
24)
25classify_task = NodeClassify(graph=embedded_graph, model=classifier)
26classify_task.train(lr=1e-3, n_epochs=400, patience=40)
27print(classify_task.evaluate())

evaluate() 返回类似 {'accuracy': 0.82, 'loss': 0.5714246034622192} 的字典。完整脚本是 hugegraph-ml/src/hugegraph_ml/examples/dgi_example.py。

GRAND 节点分类示例

 1from hugegraph_ml.data.hugegraph2dgl import HugeGraph2DGL
 2from hugegraph_ml.models.grand import GRAND
 3from hugegraph_ml.tasks.node_classify import NodeClassify
 4
 5hg2d = HugeGraph2DGL()
 6graph = hg2d.convert_graph(
 7    vertex_label="CORA_vertex",
 8    edge_label="CORA_edge",
 9)
10model = GRAND(
11    n_in_feats=graph.ndata["feat"].shape[1],
12    n_out_feats=graph.ndata["label"].unique().shape[0],
13)
14task = NodeClassify(graph, model)
15task.train(lr=1e-2, weight_decay=5e-4, n_epochs=2000, patience=100)
16print(task.evaluate())

GRAND 每次增强采样都会返回一组 logits,NodeClassify 会对列表中的每个元素分别应用掩码后再计算损失。完整脚本是 hugegraph-ml/src/hugegraph_ml/examples/grand_example.py。

排查问题

  • 连接失败:检查 HugeGraph Server 地址、端口和认证信息。
  • Schema 不匹配:示例默认使用 CORA_vertex 和 CORA_edge,自有数据需要传入实际标签。
  • ValueError: Graph is missing required node attribute ...:节点分类任务需要 ndata 中包含 feat、label、train_mask、val_mask 和 test_mask。请导入带掩码的数据集,或给 convert_graph 传入自定义的 mask_keys。
  • ValueError: dataset not supported:导入函数只接受上表列出的名称,且 import_graph_from_ogb 匹配 ogbl-collab 时不做大写转换。
  • DGL 或 PyTorch 导入失败:回到仓库根目录重新执行 uv sync --extra ml,并确认当前 Python 来自根目录 .venv。
  • bgrl_example.py 目前在导入阶段就会失败:它从 hugegraph_ml.models.bgrl 导入 MLP_Predictor,而该模块中的类名是 MLPPredictor。
  • care_gnn_example.py 读取 AMAZON_user_v 和三个 AMAZON_net_*_e 边标签,仓库内没有对应的导入函数,需要自行准备该数据集后再运行。

3.3 - HugeGraph-LLM 使用流程

本页按 Web 页面的操作顺序,说明如何建立索引、查询文档和生成 Gremlin。服务启动方式见 HugeGraph-LLM。

先准备可连接的 HugeGraph Server、生成模型和 Embedding 模型。查看配置或在 Graph Tools 手写 Gremlin 不需要模型; 文档向量化需要 Embedding,图数据抽取和答案生成还需要 LLM。Reranker 可选,初次运行可用本地 bleu。

想做什么页面入口需要准备什么
从文档建立索引1. Build RAG Index文档、Embedding;抽取图数据还需 Schema 和 LLM
根据文档或图回答问题2. (Graph)RAG & User Functions对应索引和 LLM
把问题转成 Gremlin3. Text2gremlin图 Schema、LLM;引用示例还需 Embedding 和示例索引
直接验证图数据4. Graph ToolsHugeGraph 连接和手写 Gremlin

本文截图基于 HugeGraph-LLM Web 界面,示例包含中英文提示词模式(通过环境变量 LANGUAGE 切换内置提示词语言,界面控件保持英文)。

源码启动时缺少批量问题模板

若启动时报 FileNotFoundError,且缺少的文件为 questions_template.xlsx,在已安装依赖的仓库根目录创建输入模板后重启。 已有文件会保留。模板包含完整的 6 列,只填写测试问题和预期答案,4 个模型回答列留空。

 1uv run --extra llm python - <<'PYTHON'
 2from pathlib import Path
 3from openpyxl import Workbook
 4
 5path = Path("hugegraph-llm/src/hugegraph_llm/resources/demo/questions_template.xlsx")
 6if not path.exists():
 7    workbook = Workbook()
 8    sheet = workbook.active
 9    sheet.append([
10        "Question", "Expected Answer", "Basic LLM Answer",
11        "Vector-only Answer", "Graph-only Answer", "Graph-Vector Answer",
12    ])
13    sheet.append(["Who is Sarah?", "Sarah is a 30-year-old attorney.", None, None, None, None])
14    workbook.save(path)
15PYTHON

0. 配置面板

标签页上方是可折叠的配置面板,共五个部分,包括 1. Set up the HugeGraph server.、2. Set up the LLM.、3. Set up the Embedding.、4. Set up the Reranker. 和 5. Set up the vector engine.。每部分都有独立的应用按钮,应用后会把受支持的字段写回 .env。页面顶部还会显示当前提示词语言。

在 LLM 配置的 chat、mini_tasks、text2gql 子页分别设置回答、抽取和查询生成模型。 截图使用本地 Ollama 的 qwen2.5:3b 和 mxbai-embed-large,向量引擎为 Faiss。 更换 Embedding 模型后需重建索引,避免新旧向量维数或含义不同。

1. 构建 RAG 索引

第一个标签页负责两类索引。

  • 将文档切分后写入 chunk 向量索引。
  • 按 Schema 从文档抽取顶点和边,写入 HugeGraph,并维护顶点向量索引。
flowchart TD
    A[输入文档] --> B[文本切分]
    B --> C[生成 chunk 向量]
    C --> D[写入向量索引]
    B --> E[LLM 按 Schema 抽取顶点和边]
    E --> F[写入 HugeGraph]
    F --> G[更新顶点向量索引]

输入来自 text 子页或 file 子页。上传支持 .txt、.docx 和 .pdf,可一次选择多个文件。

首次尝试可以使用下面的短文,填入 Input Doc(s)。请先选择专用测试图,避免将示例写入业务图。

1Sarah is a 30-year-old attorney. James is a journalist. Sarah has been James's roommate since 2010.

将下面的 JSON 填入 Graph Schema,保留默认抽取提示词。它只允许抽取人物及室友关系,年龄和职业可为空。

 1{
 2  "vertexlabels": [
 3    {"id": 1, "name": "person", "id_strategy": "PRIMARY_KEY",
 4     "primary_keys": ["name"], "properties": ["name", "age", "occupation"],
 5     "nullable_keys": ["age", "occupation"]}
 6  ],
 7  "edgelabels": [
 8    {"name": "roommate", "source_label": "person", "target_label": "person", "properties": ["date"]}
 9  ],
10  "propertykeys": [
11    {"name": "name", "data_type": "TEXT", "cardinality": "SINGLE"},
12    {"name": "age", "data_type": "INT", "cardinality": "SINGLE"},
13    {"name": "occupation", "data_type": "TEXT", "cardinality": "SINGLE"},
14    {"name": "date", "data_type": "TEXT", "cardinality": "SINGLE"}
15  ]
16}

页面包含文档、Schema、抽取提示词和结果区域。按下面的顺序建立图索引。只用向量检索时,完成第 1 步即可。

  1. 点击 Import into Vector,切分文档并建立 chunk 向量索引。
  2. 在 Graph Schema 填入 Schema JSON 或已有图名,再点击 Extract Graph Data (1)。检查 Output Info 中的顶点、边和属性。
  3. 确认抽取结果后点击 Load into GraphDB (2),写入 HugeGraph 并更新顶点向量。
  4. 打开 Graph Tools,执行 g.V().count() 和 g.E().count(),再查具体属性,确认数据已写入。

本例应得到 2 个顶点和 1 条边,Sarah 的年龄为 30,职业为 attorney。 图里已经有数据时,可以单独点击 Update Vid Embedding 更新顶点索引。

这些按钮旁的 Graph Extraction Split Type 下拉框可选 document、paragraph 或 sentence。document 把输入整体作为一个单元,另外两种会在抽取前先切分长文档。

页面还可以查看或清除 chunk 索引、顶点索引和图数据。清除操作会删除已有数据,执行前先确认当前图和索引是否仍被其他查询使用。

主控件下方还有两个折叠的辅助工具。

  • Graph Schema Generator 根据查询示例和少样本示例生成 Schema,填入 Graph Schema 字段。
  • Graph Extraction Prompt Generator 根据期望场景(例如社交关系、金融知识图谱)和选定的参考示例生成 Graph Extract Prompt Header。

2. GraphRAG 查询

第二个标签页提供四种回答范围,按需要选择对应索引。

控件回答依据
Basic LLM Answer直接调用 LLM,不查询文档或图
Vector-only Answerchunk 向量检索结果
Graph-only Answer图检索结果
Graph-Vector Answer图与 chunk 向量检索结果

推荐优先使用 Graph-Vector Answer,同时结合图数据检索与文档向量索引以获得更完整的事实支撑。其他范围的控件含义见上表。

截图使用下面的简短提示词。分别填入 Query Prompt 和 Keywords Extraction Prompt,其中占位符会由服务替换。 关键词输出需使用代码块中的英文前缀和冒号,姓名的大小写应与图数据一致。

1只根据检索到的上下文,用中文简洁回答问题,保留原文中的姓名。上下文不足时说明缺少信息。
2上下文: {context_str}
3问题: {query_str}
1从问题中提取人名,保留姓名原有的大小写,最多输出 {max_keywords} 个。
2只返回一行,严格使用英文冒号,格式为 KEYWORDS:姓名:1.0
3问题: {question}
  1. 输入 Who is Sarah?,将 Graph-only Answer 设为 False,Graph-Vector Answer 设为 True。
  2. 初次验证时保留 Template Num=-1 和 Rerank method=bleu,点击 Answer Question。
  3. 查看 Graph-Vector Answer,将答案中的职业、年龄等事实与原文和图数据核对。
flowchart TD
    Q[问题] --> V[查询 chunk 向量索引]
    Q --> K[抽取关键词]
    K --> M[匹配图顶点]
    M --> D{启用 Text2Gremlin}
    D -->|是| T[生成并执行 Gremlin]
    D -->|否| B[BFS 图遍历]
    T -->|失败| B
    T --> R[整理图结果]
    B --> R
    V --> S[合并与重排序]
    R --> S
    S --> A[生成答案]

图召回先用关键词精确匹配 HugeGraph 顶点,找不到时再用顶点向量做近似匹配。匹配结果会进入 Text2Gremlin;生成或执行失败时,流程可以回退到预定义的图遍历。

Template Num 控制 Text2Gremlin 在图召回中的参与方式。

  • 小于 0 时,完全跳过 Text2Gremlin,图召回直接使用预定义的图遍历。
  • 等于 0 时,不检索参考示例,使用基础生成结果。
  • 大于 0 时,从示例索引中取相应数量的相近示例,并采用带模板的生成结果。示例数量会被限制在 0 到 10 之间。

该标签页的其他控件还有 Rerank method(bleu 或 reranker)、Graph Ratio、Near neighbor first 和 Query related information,以及可编辑的 Query Prompt 和 Keywords Extraction Prompt。

单条问答面板下方是批量回归测试面板。上传 .xlsx 或 .csv 问题文件,设置 Max Lines To Show,点击 Generate Answer (Batch)。答案会显示在预览表格中,并可下载为文件。上传控件旁提供模板文件下载。

3. Text2Gremlin

第三个标签页将自然语言转换为 Gremlin,并执行生成的查询。上半部分用 .json 或 .csv 的问题与 Gremlin 对建立示例向量索引; 未上传文件时使用内置的 resources/demo/text2gremlin.csv。示例中的标签和属性应与当前图一致。

提示

若上传 CSV 构建示例向量索引后未自动召回示例模板,可直接在下面的 Prompt 模板中手动提供 Few-shot 参考示例。

复现 Sarah 查询时,使用以下输入。

  1. 将下面的 CSV 保存为 sarah-gremlin.csv,上传后点击 Build Example Vector Index,并把 Number of refer examples 设为 1。
  2. 在 Schema 填入下方的简化 Schema,只保留查询所需的类型与属性。
  3. 在 Prompt 填入下方的提示词,输入问题 Who is Sarah?,再点击 Text2Gremlin。
  4. 检查生成语句及两组 Query ... Output。本例返回 Sarah 的 age=30 和 occupation=attorney。
1query,gremlin
2Who is Sarah?,"g.V().has('person', 'name', 'Sarah').valueMap()"
1{"vertexlabels":[{"name":"person","properties":["name","age","occupation"]}],"edgelabels":[]}
 1把问题转换为 HugeGraph 的只读 Gremlin 查询。
 2按人物姓名查询时,使用 g.V().has('person', 'name', '<问题中的姓名>').valueMap()。
 3保留姓名的大小写,按姓名查询,不使用顶点 ID。
 4问题示例: Who is Peter?
 5Gremlin 示例: g.V().has('person', 'name', 'Peter').valueMap()
 6图 Schema: {schema}
 7其他示例: {example}
 8已知顶点: {vertices}
 9问题: {query}
10只返回一个 ```gremlin``` 代码块。

小模型可能生成错误 ID、大小写不符的姓名或不满足索引条件的过滤语句。应查看执行结果中的具体数据,再判断查询是否成功。 Web 页面会直接执行生成的语句,请使用专用测试图。需要只生成语句时,在 REST API 中选择相应输出类型。

自定义提示词必须保留 {query}、{schema}、{example} 和 {vertices}。缺少任一占位符时,REST API 会拒绝请求。

4. 图工具与管理工具

Graph Tools 标签页可直接对当前图执行 Gremlin 查询、手动触发图备份,并通过 beta 操作初始化 HugeGraph 演示数据。后台还有两个任务,每天凌晨 1 点自动备份图数据,以及在进程运行期间持续更新顶点 id 向量。 初始化演示数据会先清空当前图,只能在专用测试图上使用。

Admin Tools 需要密码。输入已配置的 ADMIN_TOKEN 后可查看 logs/llm-server.log 的末尾内容(每 60 秒自动刷新),并可手动刷新或清空该文件。ADMIN_TOKEN 为空或仍是占位值 xxxx 时,访问会被拒绝。

设置 ENABLE_LOGIN=True 后,Web 页面会要求基础认证,用户名固定为 rag,密码是 USER_TOKEN;REST API 则要求把 USER_TOKEN 作为 Bearer token。日志接口还要求单独配置安全的 ADMIN_TOKEN。

警告

生产环境必须启用 HugeGraph-LLM 自身的登录认证,并替换 USER_TOKEN 和 ADMIN_TOKEN,同时在防火墙或网络入口设置来源 IP 白名单。HugeGraph Server 还必须单独开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 GRAPH_USER 配置最小必要权限。AI 服务 token 不会替代 HugeGraph Server 认证。

5. 提示词语言

在 hugegraph-llm/.env 中选择一种提示词语言。

1# 英文提示词
2LANGUAGE=EN
3
4# 中文提示词
5LANGUAGE=CN

修改后重启服务。该配置选择内置提示词语言,不会自动翻译输入文档,也不属于 /rag 请求体字段。

6. REST 调用

Web 页面和 REST API 使用同一套流程。需要程序集成时使用 /rag、/rag/graph、/graph/extract 和 /text2gremlin;请求结构见 REST API。

3.4 - 配置参考

HugeGraph-LLM 从 .env 读取运行配置,提示词单独保存在 config_prompt.yaml。两者使用不同的路径解析规则;不要把提示词文件当作 .env 的一部分。

.env 路径按以下顺序解析:

  1. 若设置了环境变量 HUGEGRAPH_LLM_ENV_PATH,则使用该路径,开头的 ~ 会被展开。
  2. 从源码运行时,使用 hugegraph-llm/.env。
  3. 以已安装的包运行时,使用当前工作目录下的 .env。

该路径在导入配置模块时确定。设置 HUGEGRAPH_LLM_ENV_PATH 时,需在启动 Python 进程前设置;不能只把它写进将要读取的 .env 文件。覆盖路径使用相对路径时,以进程当前工作目录为基准。

提示词 YAML 路径按以下顺序解析:

  1. 若进程环境中设置了 HUGEGRAPH_LLM_PROMPT_CONFIG_PATH,使用该路径,并展开开头的 ~。
  2. 从源码运行时,使用 hugegraph-llm/src/hugegraph_llm/resources/demo/config_prompt.yaml。
  3. 以已安装的包运行时,使用 ${XDG_CONFIG_HOME:-~/.config}/hugegraph-llm/config_prompt.yaml。

覆盖路径的环境变量也要在进程启动前设置。相对路径以进程当前工作目录为基准。源码 Docker 镜像通过 PYTHONPATH 指向源码目录,因此默认提示词路径仍位于 hugegraph-llm/src/hugegraph_llm/resources/demo/。

运行以下命令可按配置类的默认值创建或更新文件:

1cd hugegraph-ai/hugegraph-llm
2python -m hugegraph_llm.config.generate --update

--update 默认开启,因此不带参数运行效果相同。配置模块首次导入时会为缺失的 .env 和提示词 YAML 按默认值创建文件;文件已存在时,生成器会交互询问是否覆盖。该命令会处理 HugeGraph、管理员、LLM、索引配置及提示词 YAML,不会在无确认的情况下覆盖已有文件。

.env 包含密钥和密码,不要提交到版本库。

基础选项

配置项默认值说明
LANGUAGEEN提示词语言,可选 EN、CN
CHAT_LLM_TYPEopenai回答模型,可选 openai、litellm、ollama/local
EXTRACT_LLM_TYPEopenai信息抽取模型,取值同上
TEXT2GQL_LLM_TYPEopenaiText2Gremlin 模型,取值同上
EMBEDDING_TYPEopenai嵌入模型,取值同上,也可以留空
RERANKER_TYPE空可选 cohere、siliconflow
KEYWORD_EXTRACT_TYPEllm可选 llm、textrank、hybrid
WINDOW_SIZE3TextRank 滑窗,范围 1 到 10
HYBRID_LLM_WEIGHTS0.5hybrid 模式中 LLM 结果的权重,范围 0 到 1

OpenAI 兼容接口

聊天、抽取和 Text2Gremlin 可以使用不同端点、密钥和模型。

用途API 地址密钥模型最大 token 默认值
回答OPENAI_CHAT_API_BASEOPENAI_CHAT_API_KEYOPENAI_CHAT_LANGUAGE_MODELOPENAI_CHAT_TOKENS=8192
抽取OPENAI_EXTRACT_API_BASEOPENAI_EXTRACT_API_KEYOPENAI_EXTRACT_LANGUAGE_MODELOPENAI_EXTRACT_TOKENS=256
Text2GremlinOPENAI_TEXT2GQL_API_BASEOPENAI_TEXT2GQL_API_KEYOPENAI_TEXT2GQL_LANGUAGE_MODELOPENAI_TEXT2GQL_TOKENS=4096
嵌入OPENAI_EMBEDDING_API_BASEOPENAI_EMBEDDING_API_KEYOPENAI_EMBEDDING_MODEL不适用

API 地址默认是 https://api.openai.com/v1;三个语言模型默认是 gpt-4.1-mini,嵌入模型默认是 text-embedding-3-small。

OPENAI_BASE_URL 和 OPENAI_API_KEY 可作为通用回退值。嵌入模型另有 OPENAI_EMBEDDING_BASE_URL 和 OPENAI_EMBEDDING_API_KEY 回退值。

LiteLLM

用途API 地址密钥模型最大 token 默认值
回答LITELLM_CHAT_API_BASELITELLM_CHAT_API_KEYLITELLM_CHAT_LANGUAGE_MODELLITELLM_CHAT_TOKENS=8192
抽取LITELLM_EXTRACT_API_BASELITELLM_EXTRACT_API_KEYLITELLM_EXTRACT_LANGUAGE_MODELLITELLM_EXTRACT_TOKENS=256
Text2GremlinLITELLM_TEXT2GQL_API_BASELITELLM_TEXT2GQL_API_KEYLITELLM_TEXT2GQL_LANGUAGE_MODELLITELLM_TEXT2GQL_TOKENS=4096
嵌入LITELLM_EMBEDDING_API_BASELITELLM_EMBEDDING_API_KEYLITELLM_EMBEDDING_MODEL不适用

三个语言模型默认是 openai/gpt-4.1-mini,嵌入模型默认是 openai/text-embedding-3-small。模型名通常使用 供应商/模型 格式,具体取值由 LiteLLM 服务决定。

Ollama

用途主机端口模型
回答OLLAMA_CHAT_HOSTOLLAMA_CHAT_PORTOLLAMA_CHAT_LANGUAGE_MODEL
抽取OLLAMA_EXTRACT_HOSTOLLAMA_EXTRACT_PORTOLLAMA_EXTRACT_LANGUAGE_MODEL
Text2GremlinOLLAMA_TEXT2GQL_HOSTOLLAMA_TEXT2GQL_PORTOLLAMA_TEXT2GQL_LANGUAGE_MODEL
嵌入OLLAMA_EMBEDDING_HOSTOLLAMA_EMBEDDING_PORTOLLAMA_EMBEDDING_MODEL

主机默认是 127.0.0.1,端口默认是 11434,模型名没有默认值。使用前先在 Ollama 中拉取对应模型。

重排序

配置项默认值说明
COHERE_BASE_URLhttps://api.cohere.com/v1/rerankCohere rerank 接口;CO_API_URL 可作为回退值
RERANKER_API_KEY空Cohere 或 SiliconFlow 密钥
RERANKER_MODEL空服务端支持的模型名

HugeGraph 连接与召回限制

配置项默认值说明
GRAPH_URL127.0.0.1:8080HugeGraph 地址,不拆分为 IP 和端口
GRAPH_NAMEhugegraph图名
GRAPH_USERadmin用户名
GRAPH_PWDxxx密码
GRAPH_SPACE空GraphSpace 名称
LIMIT_PROPERTYFalse是否限制返回属性;配置类按字符串读取
MAX_GRAPH_PATH10最大图路径长度
MAX_GRAPH_ITEMS30图召回的最大项目数
EDGE_LIMIT_PRE_LABEL8每个边标签的返回上限
VECTOR_DIS_THRESHOLD0.9向量距离阈值;超过阈值的结果会被忽略
TOPK_PER_KEYWORD1每个关键词的候选数
TOPK_RETURN_RESULTS20重排序后返回的结果数

向量索引后端

配置项默认值说明
CUR_VECTOR_INDEXFaiss当前使用的向量库:Faiss、Milvus 或 Qdrant
QDRANT_HOST空
QDRANT_PORT6333
QDRANT_API_KEY空
MILVUS_HOST空
MILVUS_PORT19530
MILVUS_USER空
MILVUS_PASSWORD空

FAISS 在本地运行,无需额外依赖。未安装可选依赖就选择 Milvus 或 Qdrant 时,会报错并指出缺少的包,因此需要先安装:

1cd hugegraph-ai
2uv sync --package hugegraph-llm --extra vectordb

Web 页面的 5. Set up the vector engine. 面板提供同样的选择,并会保存所选引擎的连接配置。

登录与日志接口

配置项默认值说明
ENABLE_LOGINFalse是否要求 Bearer token;配置类按字符串读取
USER_TOKEN4321Web 页面和普通 API 的 token
ADMIN_TOKENxxxx/logs 使用的管理员 token

ADMIN_TOKEN 为空或仍为 xxxx 时,/logs 会直接返回 403。

警告

生产环境必须设置 ENABLE_LOGIN=True,替换 USER_TOKEN 和 ADMIN_TOKEN,并通过防火墙或网络入口设置来源 IP 白名单。这只保护 HugeGraph-LLM;HugeGraph Server 还必须单独开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 GRAPH_USER 设置最小必要权限。两端使用不同的认证凭据。

最小 OpenAI 配置

 1LANGUAGE=CN
 2CHAT_LLM_TYPE=openai
 3EXTRACT_LLM_TYPE=openai
 4TEXT2GQL_LLM_TYPE=openai
 5EMBEDDING_TYPE=openai
 6
 7OPENAI_API_KEY=your-api-key
 8OPENAI_BASE_URL=https://api.openai.com/v1
 9OPENAI_CHAT_LANGUAGE_MODEL=gpt-4.1-mini
10OPENAI_EXTRACT_LANGUAGE_MODEL=gpt-4.1-mini
11OPENAI_TEXT2GQL_LANGUAGE_MODEL=gpt-4.1-mini
12OPENAI_EMBEDDING_MODEL=text-embedding-3-small
13
14GRAPH_URL=127.0.0.1:8080
15GRAPH_NAME=hugegraph
16GRAPH_USER=admin
17GRAPH_PWD=your-password

配置加载

配置类先提供代码默认值。当前实现会在初始化时把所选 .env 中的值写入进程环境,再初始化配置对象;若 shell 中已经有同名变量,文件中的值会覆盖它。缺少的键使用配置类默认值,空值会被忽略,未知键会被忽略。Web 页面和配置 API 可以在运行时更新当前设置,并把受支持的字段同步回 .env。手工改动 .env 后应重启服务;提示词 YAML 会在服务启动或页面加载时读取。

键名匹配不区分大小写。

配置定义位于:

  • hugegraph-llm/src/hugegraph_llm/config/llm_config.py
  • hugegraph-llm/src/hugegraph_llm/config/hugegraph_config.py
  • hugegraph-llm/src/hugegraph_llm/config/index_config.py
  • hugegraph-llm/src/hugegraph_llm/config/admin_config.py
  • hugegraph-llm/src/hugegraph_llm/config/prompt_config.py
  • hugegraph-llm/src/hugegraph_llm/config/models/base_config.py:加载与文件同步逻辑

3.5 - HugeGraph-LLM REST API

HugeGraph-LLM 演示进程同时提供 Web 页面和 REST API。默认地址是 http://localhost:8001:

1cd hugegraph-ai/hugegraph-llm
2python -m hugegraph_llm.demo.rag_demo.app \
3  --host 127.0.0.1 \
4  --port 8001

所有接口都使用 POST:

路径成功状态码用途
/rag200按所选召回方式回答问题
/rag/graph200只做图召回,不生成最终答案
/graph/extract200从文本抽取顶点和边
/text2gremlin200由自然语言生成 Gremlin
/config/graph201更新 HugeGraph 连接
/config/llm201更新语言模型
/config/embedding201更新嵌入模型
/config/rerank201更新重排序模型
/logs200流式返回服务日志

认证

在 .env 中启用登录:

1ENABLE_LOGIN=True
2USER_TOKEN=replace-with-a-secret

启用后,请求需要 Bearer token:

1Authorization: Bearer replace-with-a-secret

同一开关也会给 Gradio 页面加上基础认证,用户名固定为 rag,密码是 USER_TOKEN。token 不正确时返回 401,并带上 WWW-Authenticate: Bearer 响应头。ENABLE_LOGIN 保持 False 时所有接口都不做鉴权。

警告

生产环境必须启用 HugeGraph-LLM 自身的登录认证,并在防火墙或网络入口设置来源 IP 白名单。该认证只保护 HugeGraph-LLM 的页面和 REST API;HugeGraph Server 还必须单独开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 GRAPH_USER 配置最小必要权限。USER_TOKEN 不会替代 Server 认证。

RAG

POST /rag

根据开关返回一种或多种回答。未显式指定时只启用 graph_only。

 1curl -X POST http://localhost:8001/rag \
 2  -H 'Content-Type: application/json' \
 3  -d '{
 4    "query": "Al Pacino 出演过哪些电影?",
 5    "raw_answer": false,
 6    "vector_only": false,
 7    "graph_only": true,
 8    "graph_vector_answer": false,
 9    "max_graph_items": 30,
10    "topk_return_results": 20,
11    "vector_dis_threshold": 0.9,
12    "topk_per_keyword": 1,
13    "gremlin_tmpl_num": 1,
14    "client_config": {
15      "url": "127.0.0.1:8080",
16      "graph": "hugegraph",
17      "user": "admin",
18      "pwd": "admin",
19      "gs": "DEFAULT"
20    }
21  }'

响应只包含已启用的回答字段:

1{
2  "query": "Al Pacino 出演过哪些电影?",
3  "graph_only": "..."
4}

其他可选参数包括 graph_ratio(默认 0.5)、rerank_method(bleu 或 reranker,默认 bleu)、near_neighbor_first(默认 false)、custom_priority_info,以及三个自定义提示词字段 answer_prompt、keywords_extract_prompt 和 gremlin_prompt。省略提示词字段时使用 config_prompt.yaml 中的值。

gremlin_tmpl_num 决定图召回阶段 Text2Gremlin 的执行方式:小于 0 表示跳过 Text2Gremlin,直接使用预定义的图遍历;等于 0 表示不带示例生成 Gremlin;大于 0 表示从示例索引中取相应数量的示例。

query 为空或只有空白字符时返回 400。

POST /rag/graph

只执行图召回,不生成最终自然语言答案:

1curl -X POST http://localhost:8001/rag/graph \
2  -H 'Content-Type: application/json' \
3  -d '{
4    "query": "Al Pacino 出演过哪些电影?",
5    "get_vertex_only": false,
6    "gremlin_tmpl_num": 1,
7    "rerank_method": "bleu"
8  }'

响应的 graph_recall 可能包含 query、keywords、match_vids、graph_result_flag、gremlin、graph_result 和 vertex_degree_list。设置 get_vertex_only=true 可在顶点匹配后提前返回,此时接口会把 match_vids 替换为完整的顶点详情。

query 为空返回 400,请求类型错误返回 400,其他失败返回 500。

图抽取

POST /graph/extract

使用内联 Schema 时不会连接 HugeGraph:

 1curl -X POST http://localhost:8001/graph/extract \
 2  -H 'Content-Type: application/json' \
 3  -d '{
 4    "texts": ["Alice 在 Acme 工作。"],
 5    "schema": {
 6      "vertexlabels": [
 7        {"name": "person", "properties": ["name"]},
 8        {"name": "company", "properties": ["name"]}
 9      ],
10      "edgelabels": [
11        {
12          "name": "works_at",
13          "source_label": "person",
14          "target_label": "company",
15          "properties": []
16        }
17      ]
18    },
19    "language": "zh",
20    "split_type": "sentence",
21    "include_meta": true
22  }'

请求字段:

字段默认值说明
texts必填字符串或字符串数组;空白项会被丢弃,全部为空时报错
schema必填内联 JSON 对象或字符串,或现有图名
example_prompt提示词 YAML 中的值抽取提示词头部
extract_typeproperty_graph目前仅接受该值
languagezhzh 或 en,用于文本切分
split_typedocumentdocument、paragraph 或 sentence
include_metafalse在 meta 中加入 vertex_count、edge_count 和 text_count
client_config无仅在 schema 为图名时允许传入

内联 Schema 必须是包含 vertexlabels 和 edgelabels 两个列表的对象。每个顶点标签需要非空的 name 和非空的 properties 列表;每条边标签需要非空的 name、source_label 和 target_label。propertykeys 可选,若存在必须是列表。

若 schema 传现有图名,必须同时传入 client_config,且 client_config.graph 必须和图名相同。这里的 client_config 只接受 graph、user、pwd 和 gs,未知字段会被拒绝,且没有 url 字段:

 1{
 2  "texts": "Alice 在 Acme 工作。",
 3  "schema": "hugegraph",
 4  "client_config": {
 5    "graph": "hugegraph",
 6    "user": "admin",
 7    "pwd": "admin",
 8    "gs": "DEFAULT"
 9  }
10}

成功响应固定包含 status(始终为 succeeded)、result.vertices、result.edges、warnings 和 meta。include_meta 不为 true 时 meta 为空。

Text2Gremlin

POST /text2gremlin

1curl -X POST http://localhost:8001/text2gremlin \
2  -H 'Content-Type: application/json' \
3  -d '{
4    "query": "查找所有 person 顶点",
5    "example_num": 1,
6    "output_types": ["template_gremlin", "template_execution_result"]
7  }'

output_types 可包含:

  • match_result
  • template_gremlin
  • raw_gremlin
  • template_execution_result
  • raw_execution_result

省略该字段时默认只返回 template_gremlin;传空数组表示由实现返回全部输出。自定义 gremlin_prompt 必须包含 {query}、{schema}、{example} 和 {vertices},缺少占位符时请求校验失败,并会列出缺失的占位符。

example_num 默认是 0,表示不使用模板,取值会被限制在 0 到 10 之间。client_config 只在单次请求内覆盖 HugeGraph 连接,生成时使用的 Schema 是当前生效的图名。query 为空返回 400,生成失败返回 500。

运行时配置

POST /config/graph

1{
2  "url": "127.0.0.1:8080",
3  "graph": "hugegraph",
4  "user": "admin",
5  "pwd": "admin",
6  "gs": "DEFAULT"
7}

user 和 pwd 默认是空字符串,gs 可选。

POST /config/llm 与 POST /config/embedding

两个端点使用同一个请求模型。/config/llm 会把 chat_llm_type、extract_llm_type 和 text2gql_llm_type 一起设为相同的值;要分别设置各任务的类型,只能通过 .env 或 Web 页面。OpenAI 或 LiteLLM 示例:

1{
2  "llm_type": "openai",
3  "api_key": "your-key",
4  "api_base": "https://api.openai.com/v1",
5  "language_model": "gpt-4.1-mini",
6  "max_tokens": "4096"
7}

Ollama 请求仍要提供公共字段;api_key 和 api_base 可传空字符串:

1{
2  "llm_type": "ollama/local",
3  "api_key": "",
4  "api_base": "",
5  "language_model": "qwen2.5:7b",
6  "host": "127.0.0.1",
7  "port": "11434"
8}

POST /config/rerank

1{
2  "reranker_type": "siliconflow",
3  "reranker_model": "BAAI/bge-reranker-v2-m3",
4  "api_key": "your-key"
5}

reranker_type 可选 cohere、siliconflow。Cohere 还可以传 cohere_base_url。

四个配置端点成功时都返回 201。它们会改动进程当前配置,并可能同步到 .env。/config/llm、/config/embedding 和 /config/rerank 在应用过程中抛出异常时会回滚到原有取值,/config/graph 不会。

/rag、/rag/graph 和 /text2gremlin 的 client_config 只在单次请求期间覆盖 HugeGraph 连接,且仅应用请求中实际出现的字段。当前实现仍会临时改动进程全局设置,不适合用不同连接并发发起长请求。

日志

POST /logs

该接口要求 .env 中的 ADMIN_TOKEN 已改成安全值。请求体示例:

1{
2  "admin_token": "replace-with-an-admin-secret",
3  "log_file": "llm-server.log"
4}

log_file 默认是 llm-server.log,只能是 logs/ 目录下的文件名,不能是绝对路径、不能包含路径分隔符,也不能解析为 . 或 ..。非法文件名返回 400。

ADMIN_TOKEN 未设置或仍是占位值时,在比对 token 之前就返回 403;token 不匹配时返回内容为 Invalid admin_token 的 403 响应。

成功时返回 text/plain 流:先回放文件末尾 125 行,然后像 tail -f 一样持续输出新内容。

3.6 - Vermeer Python 客户端

vermeer-python-client 是 Vermeer 的 Python SDK。Vermeer 是使用 Go 编写、以内存计算为主的图计算引擎。该 SDK 封装了 Vermeer master 的 REST API,可以在 Python 中列出图、提交加载和计算任务、读取任务状态。导入时使用的包名是 pyvermeer。

模块没有固定 Vermeer 服务端版本,它通过 HTTP 访问 Vermeer master,调用的接口见 API 概览。

环境要求

  • 当前源码实际要求 Python 3.10 或更高版本;虽然该模块打包元数据声明 >=3.9,代码中的类型标注使用了 Python 3.10 语法
  • 一个可通过 HTTP 访问的 Vermeer master。默认 HTTP 端口为 6688;Docker 部署需发布 6688:6688,见 Vermeer 快速上手。
  • uv(推荐)或 pip

运行时依赖:requests、urllib3、python-dateutil、decorator、rich 和 setuptools。

安装

打包元数据中的发行包名是 vermeer-python-client,其版本号独立于仓库版本号管理。该包尚未发布到 PyPI,请从源码安装。

在 HugeGraph-AI 仓库根目录,使用 vermeer extra 把它安装到共用的虚拟环境中:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra vermeer
4source .venv/bin/activate

vermeer-python-client 是以可编辑路径依赖的方式接入的,并不是 uv workspace member,因此在仓库根目录直接执行 uv sync 不会安装它,必须显式指定该 extra(或使用 --all-extras)。

单独安装该模块:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai/vermeer-python-client
3uv sync
4source .venv/bin/activate

连接 Vermeer master

1from pyvermeer.client.client import PyVermeerClient
2
3client = PyVermeerClient(
4    ip="127.0.0.1",
5    port=6688,
6    token="",
7    timeout=(0.5, 15.0),
8    log_level="INFO",
9)

构造函数参数:

参数类型默认值说明
ipstr必填Vermeer master 的主机名或 IP 地址
portint必填Vermeer master 的 REST 端口
tokenstr必填原样作为 Authorization 请求头发送
timeout(float, float) 或 NoneNone连接超时和读取超时,单位为秒
log_levelstr"INFO"应用到共享 VermeerClient 日志器的级别

如果 Python 客户端运行在宿主机,ip 填宿主机可访问的 master 地址;如果运行在容器中,则填容器网络内的 master 地址。客户端只连接 master 的 HTTP API,HugeGraph PD/Store 地址则必须能由执行加载任务的 Vermeer 节点访问。

连接前需要了解的行为:

  • 当 master 不校验鉴权时,token 可以是空字符串,但不能是 None,否则会话会抛出 ValueError("Vermeer Token must be provided.")。
  • timeout 是 (连接超时, 读取超时) 二元组。VermeerConfig 自身的默认值是 (0.5, 15.0),但客户端总是把自己的参数传下去,因此不传 timeout 时实际存入的是 None,请求会一直等待。需要超时就显式传入该二元组。
  • 基础 URL 固定拼接为 http://{ip}:{port}/,即客户端只使用明文 HTTP。
  • 每个请求都会设置 Content-Type: application/json,并把 params 序列化进请求体,GET 请求也是如此。
  • 底层会话配置了对 HTTP 500、502、504 的最多 3 次重试和 0.1 的退避系数;状态码重试遵循 urllib3 默认允许的方法,POST 不在其中,因此不能依赖它自动重试任务提交。
  • log_level 设置的是名为 VermeerClient 的共享日志器的级别。它的控制台 handler 固定为 INFO,因此目前 DEBUG 级别的记录不会打印到控制台。

端到端示例

模块自带一个可运行的示例:vermeer-python-client/src/pyvermeer/demo/task_demo.py。下面的版本在其基础上增加了有截止时间的任务轮询,先等待加载成功、再读取图并提交 PageRank 计算;PD 地址和 HugeGraph 密码从环境变量读取。服务端 worker group 也必须与任务空间的分配匹配;单 worker 快速上手可将 worker_group 设为 $,保留命名组时先按 Vermeer 快速上手 将该组绑定到任务空间。

 1import os
 2import time
 3
 4from pyvermeer.client.client import PyVermeerClient
 5from pyvermeer.structure.task_data import TaskCreateRequest
 6
 7client = PyVermeerClient(
 8    ip="127.0.0.1",
 9    port=6688,
10    token=os.getenv("VERMEER_TOKEN", ""),
11    timeout=(0.5, 15.0),
12    log_level="INFO",
13)
14
15# 列出 master 上的任务
16tasks = client.tasks.get_tasks()
17print(tasks.to_dict())
18
19# 从 HugeGraph 把图数据加载到 Vermeer
20create_response = client.tasks.create_task(
21    create_task=TaskCreateRequest(
22        task_type="load",
23        graph_name="DEFAULT-example",
24        params={
25            "load.hg_pd_peers": os.environ["VERMEER_PD_PEERS"],
26            "load.hugegraph_name": "DEFAULT/example/g",
27            "load.hugegraph_username": "admin",
28            "load.hugegraph_password": os.environ["HUGEGRAPH_PASSWORD"],
29            "load.parallel": "10",
30            "load.type": "hugegraph",
31        },
32    )
33)
34print(create_response.errcode, create_response.message)
35if create_response.errcode != 0:
36    raise RuntimeError(f"Could not create load task: {create_response.message}")
37
38def wait_task(task_id, success_state, poll_timeout=300.0):
39    deadline = time.monotonic() + poll_timeout
40    while True:
41        response = client.tasks.get_task(task_id)
42        if response.errcode != 0:
43            raise RuntimeError(f"Could not read task {task_id}: {response.message}")
44        task = response.task
45        print(task_id, task.state)
46        if task.state == success_state:
47            return task
48        if task.state in ("error", "canceled"):
49            raise RuntimeError(f"Task {task_id} ended with state {task.state}")
50        remaining = deadline - time.monotonic()
51        if remaining <= 0:
52            raise TimeoutError(f"Task {task_id} did not finish within {poll_timeout}s")
53        time.sleep(min(1.0, remaining))
54
55
56# 等待加载完成后再读取图
57wait_task(create_response.task.id, success_state="loaded")
58
59# 图加载完成后查看图信息
60print(client.graph.get_graph("DEFAULT-example").to_dict())
61
62# 在已加载的图上提交 PageRank 计算
63compute_response = client.tasks.create_task(
64    create_task=TaskCreateRequest(
65        task_type="compute",
66        graph_name="DEFAULT-example",
67        params={
68            "compute.algorithm": "pagerank",
69            "compute.parallel": "10",
70            "compute.max_step": "10",
71            "output.type": "local",
72            "output.parallel": "1",
73            "output.file_path": "result/pagerank",
74        },
75    )
76)
77if compute_response.errcode != 0:
78    raise RuntimeError(f"Could not create compute task: {compute_response.message}")
79wait_task(compute_response.task.id, success_state="complete")

加载任务以 loaded 表示成功,计算任务以 complete 表示成功;error 或 canceled 会中止示例。运行前设置 VERMEER_PD_PEERS,其值是 JSON 数组字符串,例如 export VERMEER_PD_PEERS='["hugegraph-pd:8686"]';其中地址必须能由 Vermeer master 访问,PD 返回的 Store 地址也必须能由 worker 访问。只有 master 配置为 token 鉴权时才设置 VERMEER_TOKEN;不启用鉴权时空字符串可用。

示例的 output.type=local 会把结果写到执行任务的 worker 本地文件系统,文件名以 result/pagerank 为前缀。容器部署时需把 worker 的结果目录挂载出来才能从宿主机读取。poll_timeout 是客户端轮询截止时间;检查期限之间的请求仍受 HTTP 超时和 SDK 重试影响,因此实际结束时间可能越过该值。超时只停止客户端等待,不会取消服务端任务。

不要把真实的 HugeGraph 密码写死在脚本或配置文件中,请像上面这样从环境变量或凭据管理系统读取。

保存并运行文档中的端到端示例

将上方完整的增强示例代码保存为 vermeer_client_example.py,放在 hugegraph-ai/ 仓库根目录。在该目录使用已安装 vermeer extra 的 workspace 环境运行:

1uv sync --extra vermeer
2export VERMEER_PD_PEERS='["hugegraph-pd:8686"]'
3read -s -r HUGEGRAPH_PASSWORD
4export HUGEGRAPH_PASSWORD
5uv run --extra vermeer python vermeer_client_example.py

输入密码后按回车。将 hugegraph-pd:8686 替换为 Vermeer master 可访问的 PD 地址;若 master 启用了 token 鉴权,还要从本机凭据管理方式设置 VERMEER_TOKEN。上述命令运行的是文档增强示例,不是包内原始 demo。

包内原始 demo

vermeer-python-client/src/pyvermeer/demo/task_demo.py 是另一份精简示例:它把客户端端口写为 8688,把 PD 地址写为 127.0.0.1:8686,并使用 xxx 占位用户名和密码。它不会读取本页增强示例使用的环境变量,也没有任务状态轮询或 PageRank 计算。若运行该文件,需单独调整其中的服务地址和 HugeGraph 凭据;不能用它替代上面的文档示例命令。

API 概览

PyVermeerClient 以属性的方式暴露各个 API 组,目前注册了 graph 和 tasks 两个组。

client.graph

方法Vermeer 接口返回值
get_graphs()GET /graphsGraphsResponse
get_graph(graph_name)GET /graphs/{graph_name}GraphResponse

client.tasks

方法Vermeer 接口返回值
get_tasks()GET /tasksTasksResponse
get_task(task_id)GET /task/{task_id}TaskResponse
create_task(create_task)POST /tasks/createTaskCreateResponse

pyvermeer/api/master.py 和 pyvermeer/api/worker.py 目前只有许可证头,也没有注册到客户端上。因此尽管 pyvermeer/structure/ 下已经有 MasterResponse 和 WorkersResponse,master 和 worker 信息暂时还无法通过客户端获取。

client.send_request(method, endpoint, params) 是这两个组共用的请求入口。对于还没有封装的 Vermeer 接口,可以直接调用它,返回值是解析后的 JSON 字典。

请求与响应对象

TaskCreateRequest(task_type, graph_name, params) 序列化为 {"task_type": ..., "graph": ..., "params": ...}。注意 graph_name 在报文中的字段名是 graph,与 Vermeer REST API 的请求体一致。

所有响应类型都继承 BaseResponse,提供 errcode、message 属性和 to_dict() 方法。errcode 为 0 表示成功,1 表示错误,-1 表示响应体中没有该字段。

  • GraphsResponse.graphs 和 GraphResponse.graph 返回 VermeerGraph 对象,包含 name、space_name、status、create_time、update_time、vertex_count、edge_count、workers、worker_group、use_out_edges、use_property、use_out_degree、use_undirected、on_disk 和 backend_option。
  • TasksResponse.tasks、TaskResponse.task 和 TaskCreateResponse.task 返回 TaskInfo 对象,SDK 读取 id、state、create_user、create_type、create_time、start_time、update_time、graph_name、space_name、params、workers 和 error_message。
  • 时间字段由 python-dateutil 解析为 datetime 对象,空字符串会解析为 None。

当前服务端以 task_type 返回任务类型,而 SDK 的 TaskInfo.type 按 type 读取,因此该属性目前为空;服务端还返回的 statistics_result 不会被 SDK 的 TaskInfo 保留。轮询状态请使用 TaskInfo.state。这是当前源码的字段契约差异。

任务参数

客户端不会校验 params,键和值都会原样传给 Vermeer,因此可用的参数名由引擎决定,而不是由 SDK 决定。加载参数以及各算法的参数请参考 Vermeer 快速上手。

使用流程与直接调用 REST API 相同:先创建 load 任务把图读入 Vermeer,等待任务完成,再针对已加载的图创建计算任务。

异常

pyvermeer.utils.exception 定义了四种异常,都由底层的 requests 或 JSON 解析失败包装而来:

异常触发场景
ConnectErrorrequests.ConnectionError,无法连接 master
TimeOutErrorrequests.Timeout,连接或读取超时
JsonDecodeError响应体不是合法的 JSON
UnknownError请求过程中的其他失败
1from pyvermeer.utils.exception import ConnectError, TimeOutError
2
3try:
4    graphs = client.graph.get_graphs()
5except (ConnectError, TimeOutError) as error:
6    print(error)

客户端不检查响应的 HTTP 状态码,请通过返回对象的 errcode 和 message 判断是成功还是 Vermeer 端返回了错误。

代码检查

在 HugeGraph-AI 仓库根目录执行格式化和静态检查:

1./style/code_format_and_analysis.sh

源码位于 vermeer-python-client/src/pyvermeer/。目前有少量 src/tests/structure/test_task_data.py 结构测试,没有覆盖 HTTP API 的集成测试。

参考

4 - HugeGraph 图计算(OLAP)

HugeGraph-Computer 仓库包含两套部署和运行方式不同的图计算系统。通用图算法任务默认建议从 Go Vermeer 开始;需要 Java BSP/Pregel 分布式计算模型时,请使用 Computer。两者都可接入 HugeGraph,但配置和作业入口不能互换。

默认入口:Go Vermeer

flowchart TB
    Master["Master"] --> Workers["Workers"]
    Master -->|PD| PD["PD"]
    Workers -->|扫描| Store["Store"]
    Workers -.->|REST| Server["Server"]

当 load.type=hugegraph 时,Vermeer Master 通过 PD 查询分区元数据,Workers 直接扫描 HStore Store 分区。仅当 output.type=hugegraph 时,Workers 才通过 Server REST API 写回结果;其他数据源或输出配置不需要对应连接。

Java Computer

flowchart TB
    Config["作业配置"] --> Master["Master"] --> Workers["Workers"]
    Master -. BSP .-> Etcd["etcd"]
    Workers <-->|REST| Server["Server"]
    Workers <-->|HDFS| HDFS["HDFS(可选)"]

作业配置可由 Kubernetes Operator 或 YARN 提交。Workers 通过 REST API 从 HugeGraph Server 读取图数据,并可按输出配置写回计算结果;选择 HDFS 输入或输出时,Workers 直接访问 HDFS。Master 使用 etcd 协调 BSP 作业。

4.1 - HugeGraph-Vermeer 快速上手

Vermeer 高性能内存图计算:一次启动、多次执行,支持 15+ OLAP 算法及秒到分钟级计算,涵盖部署、数据加载、PageRank 和社区发现。

一、Vermeer 概述

1.1 运行架构

Vermeer 是使用 Go 编写的高性能内存优先图计算框架,支持一次启动、多次执行,以及 15+ OLAP 图算法的极速计算,大部分算法可在秒到分钟级完成。实际耗时取决于图规模、算法参数和可用资源。当前由一个 master 调度,可连接多个 worker。

master 是负责通信、转发、汇总的节点,计算量和占用资源量较少。worker 是计算节点,用于存储图数据和运行计算任务,占用大量内存和 cpu。grpc 和 rest 模块分别负责内部通信和外部调用。

启动时,程序先设置内置默认值,再读取工作目录下 config/<env>.ini 的 [default] 节,最后由显式命令行参数覆盖对应配置;例如 --env=master 读取 config/master.ini。Docker 镜像把仓库中的配置复制到 /go/bin/config/,并以 /go/bin/ 为工作目录。挂载宿主机目录到 /go/bin/config 会遮住镜像自带文件,因此该目录必须包含实际使用的 ini 文件。普通 INI 配置键不会自动映射环境变量。部署专用凭据设置还支持 VERMEER_PD_PASSWORD_FILE、VERMEER_PD_PEERS、VERMEER_HUGEGRAPH_CREDENTIALS_FILE 及文档中的签名因子/密码文件设置。

默认端口如下:

角色配置键默认地址用途
masterhttp_peer0.0.0.0:6688REST API;宿主机客户端访问此端口
mastergrpc_peer0.0.0.0:6689worker 连接 master 的 gRPC 端口
workerhttp_peer0.0.0.0:6788worker HTTP 服务
workergrpc_peer0.0.0.0:6789worker gRPC 监听地址,同时会通告给 master 供节点间通信

Docker 示例只把 master 的 HTTP 端口发布到宿主机回环地址 127.0.0.1:6688:6688;master 和 worker 的 gRPC 端口留在容器网络内部。

flowchart LR
  Client["curl / Python 客户端"] -->|"HTTP :6688"| Master["master"]
  Worker["worker"] <-->|"双向 gRPC:master :6689,worker :6789"| Master
  Master -->|"gRPC 查询分区"| PD["HugeGraph PD"]
  Worker -->|"gRPC 扫描分区"| Store["HugeGraph Store"]

1.2 运行方法

Helm:与 HugeGraph、Hubble 一起部署 Vermeer

HugeGraph Helm Chart 支持一键拉起原生 Vermeer 内存图计算引擎,默认保持关闭。 在 HugeGraph 仓库根目录下,开启 Vermeer 并启动:

1helm install hugegraph ./helm/hugegraph -n hugegraph --create-namespace \
2  -f helm/hugegraph/values-single.yaml \
3  --set vermeer.enabled=true --set vermeer.mode=standalone \
4  --wait --timeout 20m

Vermeer 核心文件与配置结构

  • helm/hugegraph/
    • examples/
      • values-vermeer-standalone.yaml单机预设(单个 Pod 同时运行 Master 与 Worker 容器)
      • values-vermeer-cluster.yaml集群预设(独立 Master Pod + 多 Worker Pods 分布式计算)
    • templates/
      • vermeer-master.yamlMaster 调度节点编排
      • vermeer-worker.yamlWorker 内存计算节点编排
      • vermeer-auth-secret.yaml管理员密码与 Hubble 内部调用服务令牌
    • docs/
      • vermeer.mdVermeer 算法调用、参数映射与运维指引

架构与运行模式:

  • 单机模式(standalone):Master 与 Worker 运行在同一个 Pod 中,开销小,适合小规模图计算测试。
  • 集群模式(cluster):设 vermeer.mode=cluster 与 vermeer.worker.replicas=3,提供独立的 Master 协调节点与多个分布式 Worker 计算节点。
  • 图服务协同:Master 通过 gRPC 向 PD 查询分区信息,Worker 直连 Store 扫描图数据切片;Hubble 会自动注入 Master 地址与通信令牌,在可视化界面中一键加载图并执行 15+ 种图算法。

核心注意事项:

  1. 保持元数据命名空间一致:保留 Chart 默认的 metadataCluster: hg-test。该值统一了 Server 的 HG_SERVER_CLUSTER 与 Store 的 PD_CLUSTER,确保 Schema 正确读取;切勿随意修改该值,以免计算加载时报 Schema missing。
  2. 访问原生 Web 控制台:easy 模式通过 <release>-vermeer-master Service 分配的 HTTP NodePort, 打开 http://<可达节点IP>:<NodePort>/;strict 默认 ClusterIP,可用 kubectl -n hugegraph port-forward svc/<release>-vermeer-master 6688:6688 在本机访问。 vermeer.service.type: null 继承模式默认值,显式 ClusterIP 保持私有,显式 NodePort 则开放需要登录的 HTTP/UI。 内部 Master/Worker RPC 与 Worker HTTP 仍保持私有;standalone / cluster 不改变上述访问选择。 在 Admin credential 处填入 <release>-vermeer-admin Secret 的 password(无需用户名),登录后获得 24 小时会话。 新密码在 easy 下为 6 位随机字母数字,strict 下为 16 位;升级与模式切换保留既有凭据。
  3. 详细镜像固定策略、持久卷配置及运维命令可参考 Helm 可选引擎指南 与 Vermeer 部署指南。
警告

生产环境必须启用 HugeGraph Server 认证与授权、IP 白名单和最小权限授权,并保留 audit-*.log 审计记录。Server Auth 不会保护 Vermeer、PD 和 Store 的独立接口;这些 HTTP、gRPC 端口必须限制在可信网络及调用方范围内,Vermeer 对外入口需配置访问控制。

独立手动部署时,默认 master.ini 配置为 auth=none,下方 Docker 示例仅发布至回环地址;若需远程访问,务必在配置文件中启用 auth=token。Helm 部署在两种模式下均要求 Token 鉴权,easy 默认仅通过 NodePort 开放原生 HTTP/UI。

下面两种 Docker 启动方式都需要先准备一个宿主机配置目录。请在 Vermeer 仓库根目录执行,将项目提供的 master.ini 和 worker.ini 模板复制到该目录;挂载会覆盖镜像里的 /go/bin/config,所以不要把空目录或整个用户主目录挂进去:

1CONFIG_DIR="$HOME/vermeer-config"
2mkdir -p "$CONFIG_DIR"
3cp config/master.ini config/worker.ini "$CONFIG_DIR/"

master.ini 保留 HTTP/gRPC 监听地址 0.0.0.0:6688 和 0.0.0.0:6689。Compose 示例为网络分配固定地址 172.20.0.10(master)和 172.20.0.11(worker),因此将复制后的 worker.ini 中这些配置设为:

1[default]
2http_peer=0.0.0.0:6788
3grpc_peer=172.20.0.11:6789
4master_peer=172.20.0.10:6689
5run_mode=worker
6worker_group=$

此单 worker 示例将 worker_group 设为 $,表示未绑定命名组时使用的通用组;请在 ini 文件中原样写入美元符号。仓库模板默认是 worker_group=default,若保留命名组,需先将它绑定到任务所在的空间或图,再提交任务。例如默认空间为 $DEFAULT 时,可执行:

1curl --fail --show-error -X POST \
2  'http://localhost:6688/admin/workers/alloc/default/%24DEFAULT'

该接口响应 errcode=0 表示绑定成功;启用 token 鉴权时还需带上授权请求头。master_peer 必须指向 worker 所在网络能访问的 master gRPC 地址。grpc_peer 同时用于 worker 监听和向 master 通告自己的地址,不能设为不可从其他容器访问的 0.0.0.0。如果更改网络子网或地址,需同步修改此处的 IP;多个 worker 还需要各自唯一且可互相访问的 grpc_peer 地址。

  1. 方案一:Docker Compose(推荐)

在 Vermeer 仓库根目录运行。可以修改仓库已有的 docker-compose.yaml,也可以使用下面的配置。仓库文件当前将整个 ~/ 挂载到配置目录且没有发布 master HTTP 端口,运行前必须按示例更换挂载路径并增加端口映射:

 1services:
 2  vermeer-master:
 3    image: hugegraph/vermeer
 4    container_name: vermeer-master
 5    ports:
 6      - "127.0.0.1:6688:6688"
 7    volumes:
 8      - /home/user/vermeer-config:/go/bin/config:ro
 9    command: --env=master
10    networks:
11      vermeer_network:
12        ipv4_address: 172.20.0.10 # master 固定地址
13
14  vermeer-worker:
15    image: hugegraph/vermeer
16    container_name: vermeer-worker
17    volumes:
18      - /home/user/vermeer-config:/go/bin/config:ro
19    command: --env=worker
20    networks:
21      vermeer_network:
22        ipv4_address: 172.20.0.11 # worker 固定地址
23
24networks:
25  vermeer_network:
26    driver: bridge
27    ipam:
28      config:
29        - subnet: 172.20.0.0/24 # 按需更换子网

把 /home/user/vermeer-config 换成上面实际的配置目录绝对路径。若修改 vermeer_network 的子网或固定 IP,也要同步更新 worker.ini 中的 grpc_peer 和 master_peer。不要复用默认 worker.ini 的 grpc_peer=0.0.0.0:6789 作为容器间通告地址。

在项目目录构建镜像并启动:

1# 构建镜像(在项目根 vermeer 目录)
2docker build -t hugegraph/vermeer .
3
4# 启动(在 vermeer 根目录)
5docker-compose up -d
6# 或使用新版 CLI:
7# docker compose up -d

查看日志 / 停止 / 删除:

1docker-compose logs -f
2docker-compose down
  1. 方案二:通过 docker run 单独启动(手动创建网络并分配静态 IP)

将 CONFIG_DIR 设为上面准备的配置目录,并确保复制后的 worker.ini 已按固定容器地址设置 grpc_peer 和 master_peer。该示例中的 CONFIG_DIR 需替换为实际的绝对路径。

构建镜像:

1docker build -t hugegraph/vermeer .

创建自定义 bridge 网络(一次性操作):

1docker network create --driver bridge \
2  --subnet 172.20.0.0/24 \
3  vermeer_network

运行 master(调整 CONFIG_DIR 为您的绝对配置路径,可以根据实际情况调整IP):

1CONFIG_DIR=/home/user/vermeer-config
2
3docker run -d \
4  --name vermeer-master \
5  --network vermeer_network --ip 172.20.0.10 \
6  -p 127.0.0.1:6688:6688 \
7  -v ${CONFIG_DIR}:/go/bin/config:ro \
8  hugegraph/vermeer \
9  --env=master

运行 worker:

1docker run -d \
2  --name vermeer-worker \
3  --network vermeer_network --ip 172.20.0.11 \
4  -v ${CONFIG_DIR}:/go/bin/config:ro \
5  hugegraph/vermeer \
6  --env=worker

查看日志 / 停止 / 删除:

1docker logs -f vermeer-master
2docker logs -f vermeer-worker
3
4docker stop vermeer-master vermeer-worker
5docker rm vermeer-master vermeer-worker
6
7# 删除自定义网络(如果需要)
8docker network rm vermeer_network
  1. 方案三:从源码构建

构建。具体请参照 Vermeer Readme。

1go build

从 Vermeer 仓库根目录启动,例如 ./vermeer --env=master 和 ./vermeer --env=worker01。worker01.ini 中的 grpc_peer 应填写可由 master 和其他 worker 访问、且本机可以绑定的地址;master_peer 指向 master 的 gRPC 监听地址。

启动 master 后,在宿主机验证 HTTP 端口:

1curl --fail --show-error http://localhost:6688/graphs

请求应返回 HTTP 200,JSON 响应中的 errcode 为 0。

二、任务创建类 rest api

2.1 简介

创建任务的流程是先提交 load 任务,等待图加载完成,再提交 compute 任务。同一张已加载的图可重复用于计算,不会因任务完成而自动删除。异步接口返回创建结果和任务信息(包括任务 ID),不代表任务已经完成;同步接口会一直等待任务进入成功或失败状态,调用方及代理的 HTTP 超时需足够长。任务状态可通过查询接口读取:加载成功为 loaded,计算成功为 complete,失败为 error,取消为 canceled,其余状态仍在等待或执行中。图在加载中或错误状态时不能用于计算;删除图要求图处于可删除状态且当前未被使用。

可以使用的 url 如下:

  • 异步接口:POST http://master_ip:port/tasks/create,从响应的 task.id 取得任务 ID。
  • 同步接口:POST http://master_ip:port/tasks/create/sync,等待该任务结束后返回。
  • 查询单个任务:GET http://master_ip:port/task/{task_id};响应中的 errcode 为 0 表示查询成功,再按 task.state 判断业务状态。异步任务应在客户端设置轮询截止时间;到时只停止客户端等待,不会自动取消服务端任务。

2.2 加载图数据

以下示例列出常用的加载参数;引擎会按具体加载器读取参数,未被加载器使用的键不会改变行为。

vermeer提供三种加载方式:

  1. 从本地加载

load.vertex_files 和 load.edge_files 是“worker 地址主机部分到文件路径”的映射;路径由对应 worker 进程读取。容器部署时,数据文件必须先挂载进 worker 容器,并填写容器内路径。在上面的 Compose 示例中,应将主机数据目录挂到 worker 的 /data(例如增加 - /host/data:/data:ro),并把映射键设为 grpc_peer 中的 172.20.0.11;其他部署则使用各自 worker 上报地址的主机部分。

可以预先获取数据集,例如 twitter-2010 数据集。获取方式:https://snap.stanford.edu/data/twitter-2010.html,第一个 twitter-2010.txt.gz 即可。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "load",
 4 "graph": "testdb",
 5 "params": {
 6  "load.parallel": "50",
 7  "load.type": "local",
 8  "load.vertex_files": "{\"172.20.0.11\":\"/data/twitter-2010.v_[0,99]\"}",
 9  "load.edge_files": "{\"172.20.0.11\":\"/data/twitter-2010.e_[0,99]\"}",
10  "load.use_out_degree": "1",
11  "load.use_outedge": "1"
12 }
13}
  1. 从hugegraph加载

request 示例:

将请求中的地址、图名和凭据替换为实际连接信息。

 1POST http://localhost:6688/tasks/create
 2{
 3  "task_type": "load",
 4  "graph": "testdb",
 5  "params": {
 6    "load.parallel": "50",
 7    "load.type": "hugegraph",
 8    "load.hg_pd_peers": "[\"<pd-address-reachable-from-vermeer>:8686\"]",
 9    "load.hugegraph_name": "DEFAULT/hugegraph2/g",
10    "load.hugegraph_username": "admin",
11    "load.hugegraph_password": "<your-password-here>",
12    "load.use_out_degree": "1",
13    "load.use_outedge": "1"
14  }
15}

Vermeer master 使用 load.hg_pd_peers 连接 PD 并查询分区,worker 再连接 PD 返回的 Store 地址读取数据。因此这些服务地址必须能从对应的 Vermeer 容器或主机访问;在 Docker 容器里,127.0.0.1 指向容器自身,不能用来代替宿主机或另一容器的地址。

  1. 从hdfs加载

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3  "task_type": "load",
 4  "graph": "testdb",
 5  "params": {
 6    "load.parallel": "50",
 7    "load.type": "hdfs",
 8    "load.hdfs_namenode": "name_node1:9000",
 9    "load.hdfs_conf_path": "/path/to/conf",
10    "load.krb_realm": "EXAMPLE.COM",
11    "load.krb_name": "user@EXAMPLE.COM",
12    "load.krb_keytab_path": "/path/to/keytab",
13    "load.krb_conf_path": "/path/to/krb5.conf",
14    "load.hdfs_use_krb": "1",
15    "load.vertex_files": "/data/graph/vertices",
16    "load.edge_files": "/data/graph/edges",
17    "load.use_out_degree": "1",
18    "load.use_outedge": "1"
19  }
20}

2.3 输出计算结果

当前有实际写入器的结果方式为 local、hdfs 和 hugegraph,通过 output.type 指定;none 表示不写出结果。源码保留 afs 类型常量,但当前主线没有注册 AFS 加载器或写入器。指定 output.need_statistics 为 1 时,统计结果会写入任务信息;统计算子的适用范围取决于对应算法实现。

以下示例列出常用的计算和结果输出参数;算法支持的参数以 Vermeer 当前实现为准。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "pagerank",
 7 "compute.parallel": "10",
 8 "compute.max_step": "10",
 9 "output.type": "local",
10 "output.parallel": "1",
11 "output.file_path": "result/pagerank"
12  }
13}

output.type=local 的结果写在执行任务的 worker 本地文件系统中;容器部署时,如需从宿主机读取结果,请将 worker 的输出目录挂载出来。

三、支持的算法

3.1 PageRank

PageRank 算法又称网页排名算法,是一种由搜索引擎根据网页(节点)之间相互的超链接进行计算的技

术,用来体现网页(节点)的相关性和重要性。

  • 如果一个网页被很多其他网页链接到,说明这个网页比较重要,也就是其 PageRank 值会相对较高。
  • 如果一个 PageRank 值很高的网页链接到其他网页,那么被链接到的网页的 PageRank 值会相应地提高。

PageRank 算法适用于网页排序、社交网络重点人物发掘等场景。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "pagerank",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/pagerank",
11 "compute.max_step":"10"
12 }
13}

3.2 WCC(弱连通分量)

弱连通分量,计算无向图中所有联通的子图,输出各顶点所属的弱联通子图 id,表明各个点之间的连通性,区分不同的连通社区。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "wcc",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/wcc",
11 "compute.max_step":"10"
12 }
13}

3.3 LPA(标签传播)

标签传递算法,是一种图聚类算法,常用在社交网络中,用于发现潜在的社区。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "lpa",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/lpa",
11 "compute.max_step":"10"
12 }
13}

3.4 Degree Centrality(度中心性)

度中心性算法,算法用于计算图中每个节点的度中心性值,支持无向图和有向图。度中心性是衡量节点重要性的重要指标,节点与其它节点的边越多,则节点的度中心性值越大,节点在图中的重要性也就越高。在无向图中,度中心性的计算是基于边信息统计节点出现次数,得出节点的度中心性的值,在有向图中则基于边的方向进行筛选,基于输入边或输出边信息统计节点出现次数,得到节点的入度值或出度值。它表明各个点的重要性,一般越重要的点度数越高。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "degree",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/degree",
11 "degree.direction":"both"
12 }
13}

3.5 Closeness Centrality(紧密中心性)

紧密中心性(Closeness Centrality)用于计算一个节点到所有其他可达节点的最短距离的倒数,进行累积后归一化的值。紧密中心度可以用来衡量信息从该节点传输到其他节点的时间长短。节点的“Closeness Centrality”越大,其在所在图中的位置越靠近中心,适用于社交网络中关键节点发掘等场景。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "closeness_centrality",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/closeness_centrality",
11 "closeness_centrality.sample_rate":"0.01"
12 }
13}

3.6 Betweenness Centrality(中介中心性算法)

中介中心性算法(Betweeness Centrality)判断一个节点具有"桥梁"节点的值,值越大说明它作为图中两点间必经路径的可能性越大,典型的例子包括社交网络中的共同关注的人。适用于衡量社群围绕某个节点的聚集程度。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "betweenness_centrality",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/betweenness_centrality",
11 "betweenness_centrality.sample_rate":"0.01"
12 }
13}

3.7 Triangle Count(三角形计数)

三角形计数算法,用于计算通过每个顶点的三角形个数,适用于计算用户之间的关系,关联性是不是成三角形。三角形越多,代表图中节点关联程度越高,组织关系越严密。社交网络中的三角形表示存在有凝聚力的社区,识别三角形有助于理解网络中个人或群体的聚类和相互联系。在金融网络或交易网络中,三角形的存在可能表示存在可疑或欺诈活动,三角形计数可以帮助识别可能需要进一步调查的交易模式。

输出的结果为 每个顶点对应一个 Triangle Count,即为每个顶点所在三角形的个数。

注:该算法为无向图算法,忽略边的方向。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "triangle_count",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/triangle_count"
11 }
12}

3.8 K-Core

K-Core 算法,标记所有度数为 K 的顶点,适用于图的剪枝,查找图的核心部分。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "kcore",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/kcore",
11 "kcore.degree_k":"5"
12 }
13}

3.9 SSSP(单元最短路径)

单源最短路径算法,求一个点到其他所有点的最短距离。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "sssp",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/degree",
11 "sssp.source":"tom"
12 }
13}

3.10 KOUT

以一个点为起点,获取这个点的 k 层的节点。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "kout",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/kout",
11 "kout.source":"tom",
12 "compute.max_step":"6"
13 }
14}

3.11 Louvain

Louvain 算法是一种基于模块度的社区发现算法。其基本思想是网络中节点尝试遍历所有邻居的社区标签,并选择最大化模块度增量的社区标签。在最大化模块度之后,每个社区看成一个新的节点,重复直到模块度不再增大。

Vermeer 上实现的分布式 Louvain 算法受节点顺序、并行计算等因素影响,并且由于 Louvain 算法由于其遍历顺序的随机导致社区压缩也具有一定的随机性,导致重复多次执行可能存在不同的结果。但整体趋势不会有大的变化。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "louvain",
 7 "compute.parallel":"10",
 8 "compute.max_step":"1000",
 9 "louvain.threshold":"0.0000001",
10 "louvain.resolution":"1.0",
11 "louvain.step":"10",
12 "output.type":"local",
13 "output.parallel":"1",
14 "output.file_path":"result/louvain"
15  }
16 }

3.12 Jaccard 相似度系数

Jaccard index , 又称为 Jaccard 相似系数(Jaccard similarity coefficient)用于比较有限样本集之间的相似性与差异性。Jaccard 系数值越大,样本相似度越高。用于计算一个给定的源点,与图中其他所有点的 Jaccard 相似系数。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "jaccard",
 7 "compute.parallel":"10",
 8 "compute.max_step":"2",
 9 "jaccard.source":"123",
10 "output.type":"local",
11 "output.parallel":"1",
12 "output.file_path":"result/jaccard"
13 }
14}

3.13 Personalized PageRank

个性化的 pagerank 的目标是要计算所有节点相对于用户 u 的相关度。从用户 u 对应的节点开始游走,每到一个节点都以 1-d 的概率停止游走并从 u 重新开始,或者以 d 的概率继续游走,从当前节点指向的节点中按照均匀分布随机选择一个节点往下游走。用于给定一个起点,计算此起点开始游走的个性化 pagerank 得分。适用于社交推荐等场景。

由于计算需要使用出度,需要在读取图时需要设置 load.use_out_degree 为 1。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "ppr",
 7 "compute.parallel":"100",
 8 "compute.max_step":"10",
 9 "ppr.source":"123",
10 "ppr.damping":"0.85",
11 "ppr.diff_threshold":"0.00001",
12 "output.type":"local",
13 "output.parallel":"1",
14 "output.file_path":"result/ppr"
15 }
16}

3.14 全图 Kout

计算图的所有节点的k度邻居(不包含自己以及1~k-1度的邻居),由于全图kout算法内存膨胀比较厉害,目前k限制在1和2,另外,全局kout算法支持过滤功能( 参数如:“compute.filter”:“risk_level==1”),在计算第k度的是时候进行过滤条件的判断,符合过滤条件的进入最终结果集,算法最终输出是符合条件的邻居个数。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "kout_all",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"10",
10 "output.file_path":"result/kout",
11 "compute.max_step":"2",
12 "compute.filter":"risk_level==1"
13 }
14}

3.15 集聚系数 clustering coefficient

集聚系数表示一个图中节点聚集程度的系数。在现实的网络中,尤其是在特定的网络中,由于相对高密度连接点的关系,节点总是趋向于建立一组严密的组织关系。集聚系数算法(Cluster Coefficient)用于计算图中节点的聚集程度。本算法为局部集聚系数。局部集聚系数可以测量图中每一个结点附近的集聚程度。

request 示例:

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "clustering_coefficient",
 7 "compute.parallel":"100",
 8 "compute.max_step":"10",
 9 "output.type":"local",
10 "output.parallel":"1",
11 "output.file_path":"result/cc"
12 }
13}

3.16 SCC(强连通分量)

在有向图的数学理论中,如果一个图的每一个顶点都可从该图其他任意一点到达,则称该图是强连通的。在任意有向图中能够实现强连通的部分我们称其为强连通分量。它表明各个点之间的连通性,区分不同的连通社区。

 1POST http://localhost:6688/tasks/create
 2{
 3 "task_type": "compute",
 4 "graph": "testdb",
 5 "params": {
 6 "compute.algorithm": "scc",
 7 "compute.parallel":"10",
 8 "output.type":"local",
 9 "output.parallel":"1",
10 "output.file_path":"result/scc",
11 "compute.max_step":"200"
12 }
13}

🚧, 后续随时更新完善,欢迎随时提出建议和意见。

4.2 - HugeGraph-Computer 快速上手

1. 组件说明

HugeGraph-Computer 是基于 BSP(Bulk Synchronous Parallel,批量同步并行)模型的 Java 分布式图计算框架,算法按超步迭代运行。它可由 Kubernetes Operator 或 YARN 调度,也可在单机上启动 master 和 worker 进程进行小规模试跑。

它与同一仓库中的 Vermeer 是两套实现:Computer 使用 Java/BSP 运行时,面向分布式计算;Vermeer 是 Go 实现的内存图计算平台,采用 master-worker 结构。两者共享 HugeGraph 数据源,但部署和任务配置不能互换。

Computer 支持从 HugeGraph 或 HDFS 读取图数据,并可将结果写回 HugeGraph 或 HDFS。运行时可把部分数据溢写到磁盘;能否完成任务仍取决于输入规模、资源和配置,不应把溢写能力理解为不受资源限制。

2. 前置条件与连接

构建和运行需要 JDK 11 或更高版本。源码构建还需要 Maven 3.5 或更高版本。PageRank 示例要求一个已启动且包含待计算图数据的 HugeGraph-Server,以及可供 master、worker 访问的 etcd。

服务示例地址或端口用途
HugeGraph-Serverhttp://127.0.0.1:8080读取图数据并写回算法结果;以 hugegraph.url 为准。
etcdhttp://127.0.0.1:2379BSP 作业协调;以 bsp.etcd_endpoints 为准。
Computer master RPCTCP 8190worker 连接 master;发行配置中的端口。
Computer worker 数据传输本地默认由系统分配;K8s Operator 默认 8099worker 之间传输顶点和消息。跨主机时需保证公告地址和端口可达。
MinIO(K8s 清单)HTTP 9000用于输入分区快照。Computer 1.7.0 清单把 Service 的 9000 错映射到 MinIO Console 的 9090;启用快照前需将 targetPort 改为 9000。默认 snapshot.write=false、snapshot.load=false,不启用快照时无需访问 MinIO。
cert-manager(K8s)集群内服务Operator 清单使用 cert-manager.io/v1 的 Certificate、Issuer 和 CA 注入功能;部署 Operator 前必须先安装兼容版本。
HDFS按集群配置仅当输入或输出配置为 HDFS 时需要。

Kubernetes 作业中的 hugegraph.url 必须是各计算 Pod 都能访问的地址,不能填仅在个人电脑上可用的 localhost。如果启用了 HugeGraph 认证,应在配置中填写用户名和密码,并为 REST 查询使用对应凭据。

警告

生产环境必须为 HugeGraph Server 开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 Computer 使用只具备作业所需读写权限的专用账号,并为 Server 网络入口设置来源 IP 白名单。hugegraph.username 和 hugegraph.password 只是 Computer 连接 Server 的凭据,不能替代 Server 端认证。

更多配置项见Computer 配置参考。

3. 获取源码并构建发行包

Apache HugeGraph 下载目录按版本提供 Computer 源码包,不提供单独的预编译 Computer 二进制包。下面以 VERSION=1.7.0 为例;该发布版的源码包和构建产物文件名含 -incubating-,其他版本请按下载目录中的实际文件名调整。

 1VERSION=1.7.0 # 替换为要下载的发布版本
 2ARCHIVE="apache-hugegraph-computer-incubating-${VERSION}-src.tar.gz"
 3DOWNLOAD_BASE="https://downloads.apache.org/hugegraph/${VERSION}"
 4curl -fLO "${DOWNLOAD_BASE}/${ARCHIVE}"
 5curl -fLO "${DOWNLOAD_BASE}/${ARCHIVE}.sha512"
 6curl -fLO "${DOWNLOAD_BASE}/${ARCHIVE}.asc"
 7curl -fLO https://downloads.apache.org/hugegraph/KEYS
 8shasum -a 512 -c "${ARCHIVE}.sha512"
 9gpg --import KEYS
10gpg --verify "${ARCHIVE}.asc" "${ARCHIVE}"
11tar -xzf "${ARCHIVE}"
12cd "apache-hugegraph-computer-incubating-${VERSION}-src/computer"
13mvn clean package -DskipTests
14tar -xzf "target/apache-hugegraph-computer-incubating-${VERSION}.tar.gz"
15cd "apache-hugegraph-computer-incubating-${VERSION}"

从当前 master 构建时可直接克隆并打包:

1git clone https://github.com/apache/hugegraph-computer.git
2cd hugegraph-computer/computer
3mvn clean package -DskipTests

发行包由 computer/computer-dist 组装,包含 bin/start-computer.sh、运行依赖 lib/、内置算法 algorithm/builtin-algorithm.jar 及默认配置 conf/computer.properties、conf/log4j2.xml。源码默认配置位于 computer/computer-dist/src/assembly/static/conf/computer.properties。1.7.0 发布源码的构建产物带 -incubating-,当前 master 的发行名不带该标记,且版本号由源码 POM 决定;不要混用两种源码对应的 tar 包名。

4. 单机运行 PageRank

先编辑发行目录中的 conf/computer.properties,按实际环境修改 HugeGraph 地址、图名和认证信息,并确认 bsp.etcd_endpoints 指向可访问的 etcd。默认配置已选择内置 PageRankParams;master 和 worker 必须使用同一份配置及相同的 job.id。每个并行作业应使用不同的 job.id。

在两个终端中都从发行目录启动进程。启动脚本默认读取 conf/computer.properties,也可用 -c 指定配置文件。

1# 终端一:启动 master
2bin/start-computer.sh -d local -r master
1# 终端二:启动 worker
2bin/start-computer.sh -d local -r worker

master 会等待配置要求的 worker 注册后运行作业。查看两个终端输出;默认日志配置也会在当前发行目录的 logs/ 下写入 master 和 worker 日志。只有进程启动成功并不代表计算完成,应确认 master 日志中输入、超步计算和输出阶段均正常结束。

PageRank 参数类将结果写回 HugeGraph,属性名为 page_rank。运行前先检查图中每个目标顶点类型都允许此属性;Computer 会按 DOUBLE、OLAP_COMMON 创建属性键,但不会把它加入顶点类型。若属性键不存在,可先创建:

1curl --fail --request POST \
2  --header 'Content-Type: application/json' \
3  --data '{"name":"page_rank","data_type":"DOUBLE","cardinality":"SINGLE","write_type":"OLAP_COMMON"}' \
4  'http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/schema/propertykeys'

如果该属性键已存在,确认其类型为 DOUBLE 且 write_type 为 OLAP_COMMON。先列出图中的顶点类型,再对每个要计算的类型添加可空的 page_rank 属性;把示例中的 person 替换为实际类型名:

1curl --fail --compressed \
2  'http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/schema/vertexlabels'
3
4curl --fail --request PUT \
5  --header 'Content-Type: application/json' \
6  --data '{"name":"person","properties":["page_rank"],"nullable_keys":["page_rank"]}' \
7  'http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/schema/vertexlabels/person?action=append'

若图当前读模式不显示 OLAP 写入,可由管理员把读模式设为 ALL:

1curl --fail --request PUT \
2  --header 'Content-Type: application/json' \
3  --data '"ALL"' \
4  'http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/graph_read_mode'

查询顶点以确认结果属性:

1curl --fail --compressed \
2  'http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices?limit=3'

需要认证时,在 curl 命令中添加 --user "$HG_USER:$HG_PASSWORD"。读模式接口和权限说明见图读模式 REST API。

5. 在 Kubernetes 中运行 PageRank

先确保 HugeGraph-Server 对计算 Pod 可达,并按 cert-manager 官方安装文档安装与集群兼容的 cert-manager。Computer Operator 清单会部署 Operator、etcd 和 MinIO;CRD 与 Operator 清单应使用同一 Computer 发行版本。下面以 1.7.0 发布版为例:

1VERSION=1.7.0 # CRD 和 Operator 清单使用同一发布版本
2kubectl apply -f "https://raw.githubusercontent.com/apache/hugegraph-computer/${VERSION}/computer/computer-k8s-operator/manifest/hugegraph-computer-crd.v1.yaml"
3kubectl apply -f "https://raw.githubusercontent.com/apache/hugegraph-computer/${VERSION}/computer/computer-k8s-operator/manifest/hugegraph-computer-operator.yaml"
4kubectl rollout status deployment/hugegraph-computer-operator-controller-manager \
5  -n hugegraph-computer-operator-system --timeout=120s
可选:启用 MinIO 快照(1.7.0)

1.7.0 清单中的 MinIO Service 把 S3 API 的 9000 端口映射到了 Console 的 9090;启用快照时先修正映射,并将 snapshot.minio_endpoint 设为 http://hugegraph-computer-operator-minio.hugegraph-computer-operator-system.svc:9000。默认不启用快照时可跳过。

1kubectl patch service hugegraph-computer-operator-minio \
2  -n hugegraph-computer-operator-system \
3  --type=json \
4  -p='[{"op":"replace","path":"/spec/ports/0/targetPort","value":9000}]'

替换 HugeGraph 地址为计算 Pod 可访问的服务地址后,提交 HugeGraphComputerJob。示例使用官方 Docker Hub 的 hugegraph/hugegraph-computer:latest,并引用镜像内置的 PageRank JAR;自定义算法 JAR 可预置在镜像内通过 jarFile 指定,也可用 remoteJarUri 从 HTTP(S) 地址下载。分区数需不小于 worker 数量。

将以下 YAML 保存为 pagerank-job.yaml,然后应用该文件:

 1apiVersion: operator.hugegraph.apache.org/v1
 2kind: HugeGraphComputerJob
 3metadata:
 4  namespace: hugegraph-computer-operator-system
 5  name: pagerank-sample
 6spec:
 7  jobId: pagerank-sample
 8  algorithmName: page_rank
 9  image: hugegraph/hugegraph-computer:latest # 官方 Docker Hub 镜像
10  jarFile: /hugegraph/hugegraph-computer/algorithm/builtin-algorithm.jar
11  pullPolicy: IfNotPresent
12  workerInstances: 1
13  masterCpu: 500m
14  workerCpu: 500m
15  masterMemory: 1Gi
16  workerMemory: 2Gi
17  computerConf:
18    job.partitions_count: "1"
19    algorithm.params_class: org.apache.hugegraph.computer.algorithm.centrality.pagerank.PageRankParams
20    hugegraph.url: http://hugegraph-server:8080
21    hugegraph.name: hugegraph
1kubectl apply -f pagerank-job.yaml
2kubectl get hcjob pagerank-sample -n hugegraph-computer-operator-system --watch

SUCCEEDED 表示作业完成。Operator 默认会在作业完成后删除 CR 和计算资源;需要保留结果或排查失败作业时,可按需展开下方说明。

可选:保留作业状态、查看日志或清理资源

Operator 默认 AUTO_DESTROY_POD=true,短作业的 CR 和 Pod 可能在查看前被清理。若要保留它们,请在提交作业前关闭该选项,并等待 Controller 新 Pod 就绪后再提交;该设置必须改在 Java Operator 的 controller 容器中:

1kubectl set env deployment/hugegraph-computer-operator-controller-manager \
2  -n hugegraph-computer-operator-system \
3  --containers=controller AUTO_DESTROY_POD=false
4kubectl rollout status deployment/hugegraph-computer-operator-controller-manager \
5  -n hugegraph-computer-operator-system --timeout=120s

查看运行信息或失败日志:

1kubectl logs --follow <master-pod-name> -n hugegraph-computer-operator-system
2kubectl logs --follow <worker-pod-name> -n hugegraph-computer-operator-system

查询完结果后删除 CR 以清理关联资源,并恢复默认策略:

1kubectl delete hcjob pagerank-sample -n hugegraph-computer-operator-system
2kubectl set env deployment/hugegraph-computer-operator-controller-manager \
3  -n hugegraph-computer-operator-system \
4  --containers=controller AUTO_DESTROY_POD=true

PageRank 写回 HugeGraph 后按上一节设置读模式并查询。若改用 HDFS 输出,结果位于 output.hdfs_path_prefix/<job.id>/ 下,文件名和分区布局由作业配置决定。

完整 CRD 字段见Computer 配置参考中的 CRD 说明。

6. 内置算法与开发入口

当前源码中的内置算法包括:

  • 中心性:PageRank、Betweenness Centrality、Closeness Centrality、Degree Centrality。
  • 社区与结构:Clustering Coefficient、K-core、LPA、Triangle Count、WCC。
  • 路径与采样:环检测、带过滤的环检测、单源最短路径、Random Walk。

算法实现位于 computer/computer-algorithm。自定义算法需要遵循 Computer API 并打包为可加载的 JAR;模块划分和开发入口见Computer README。

4.3 - HugeGraph-Computer 配置参考

Computer 配置选项

表格中的默认值来自 computer-api 模块的 ComputerOptions.java;发行包的 conf/computer.properties 显式设置的值以“代码默认值(发行包:实际值)”标注。rpc.* 等通用配置由 HugeGraph Commons 提供,以下会单独标出发行包实际值。

配置文件从哪里来

  • 源码模板:computer/computer-dist/src/assembly/static/conf/computer.properties;日志配置模板为同目录的 log4j2.xml。Maven package 阶段将模板复制进发行目录的 conf/,并将运行依赖和内置算法 JAR 装入 lib/、algorithm/。模板由源码维护,没有单独的配置生成命令。
  • 单机、YARN:启动脚本默认读取发行目录的 conf/computer.properties,可使用 bin/start-computer.sh -c <配置文件路径> 覆盖;master 和 worker 应读到同一组作业参数。
  • Kubernetes Operator:用户在 CRD 的 spec.computerConf 中提供键值;Operator 将它写成 ConfigMap,挂载为容器内的 computer.properties。Operator 会补入作业 ID、worker 数量、Pod 地址和未指定时的 etcd 地址,并在未指定或设为 0 时将数据传输端口设为 8099、master RPC 端口设为 8190。transport.server_host 与 rpc.server_host 会被设置为 Pod IP。作业容器启动脚本只对 ${POD_IP}、${HOSTNAME}、${POD_NAME}、${POD_NAMESPACE} 做环境变量替换。
  • Kubernetes 作业镜像必须包含 Computer 运行时。算法 JAR 可以预置在镜像内并由 CRD 的 jarFile 指向,也可以通过 remoteJarUri 设置 HTTP(S) 地址,让启动脚本下载并加载。示例与字段见Computer 快速上手及下方 CRD 表。

Apache HugeGraph 下载目录提供各发布版本的 Computer 源码包,不提供单独的预编译二进制包。1.7.0 的发布源码包名含 -incubating-;在该 tag 的 computer/ Maven 聚合工程运行 mvn clean package -DskipTests 后,发行包也带 -incubating-。当前 master 的发行名不含该标记,版本号由 POM 决定。源码包不能作为已构建发行包直接启动。

警告

表格中的空 HugeGraph 凭据和 MinIO 示例密钥仅适用于本地或演示环境。生产环境必须为 HugeGraph Server 开启认证与授权(见认证与授权说明)并保留 Server 审计日志(标准日志文件为 audit-*.log),为 Computer 配置最小必要权限的 Server 账号,并为 Server 网络入口设置来源 IP 白名单;不要将示例 MinIO 密钥用于生产。


1. 基础配置

HugeGraph-Computer 核心作业设置。

配置项默认值说明
hugegraph.urlhttp://127.0.0.1:8080HugeGraph 服务器 URL,用于加载数据和写回结果。
hugegraph.namehugegraph图名称,用于加载数据和写回结果。
hugegraph.username"" (空)HugeGraph 认证用户名(如果未启用认证则留空)。
hugegraph.password"" (空)HugeGraph 认证密码(如果未启用认证则留空)。
job.idlocal_0001 (打包: local_001)YARN 集群或 K8s 集群上的作业标识符。
job.namespace"" (空)可选的 etcd 作业键名前缀,可用于隔离不同命名空间;它不是 Kubernetes metadata.namespace,Operator 不会自动填入。
job.workers_count1执行一个图算法作业的 Worker 数量。在 K8s 中由 Operator 设置。
job.partitions_count1执行一个图算法作业的分区数量。
job.partitions_thread_nums4分区并行计算的线程数量。

2. 算法配置

计算逻辑的算法特定配置。

配置项默认值说明
algorithm.params_classComputerOptions.Null 占位类必填。用于在算法运行前传递算法参数的类。
algorithm.result_classComputerOptions.Null 占位类顶点值的类,用于存储顶点的计算结果。
algorithm.message_classComputerOptions.Null 占位类计算顶点时传递的消息类。

3. 输入配置

从 HugeGraph 或其他数据源加载输入数据的配置。

3.1 输入源

配置项默认值说明
input.source_typehugegraph-server加载输入数据的源类型,允许值:[‘hugegraph-server’, ‘hugegraph-loader’]。‘hugegraph-loader’ 表示使用 hugegraph-loader 从 HDFS 或文件加载数据。如果使用 ‘hugegraph-loader’,请配置 ‘input.loader_struct_path’ 和 ‘input.loader_schema_path’。
input.loader_struct_path"" (空)Loader 输入的结构路径,仅在 input.source_type=hugegraph-loader 时生效。
input.loader_schema_path"" (空)Loader 输入的 Schema 路径,仅在 input.source_type=hugegraph-loader 时生效。

3.2 输入分片

配置项默认值说明
input.split_size1048576 (1 MB)输入分片大小(字节)。
input.split_max_splits10000000最大输入分片数量。
input.split_page_size500流式加载输入分片数据的页面大小。
input.split_fetch_timeout300获取输入分片的超时时间(秒)。

3.3 输入处理

配置项默认值说明
input.filter_classorg.apache.hugegraph.computer.core.input.filter.DefaultInputFilter创建输入过滤器对象的类。输入过滤器用于根据用户需求过滤顶点边。
input.edge_directionOUT要加载的边的方向,允许值:[OUT, IN, BOTH]。当值为 BOTH 时,将加载 OUT 和 IN 两个方向的边。
input.edge_freqMULTIPLE一对顶点之间可以存在的边的频率,允许值:[SINGLE, SINGLE_PER_LABEL, MULTIPLE]。SINGLE 表示一对顶点之间只能存在一条边(通过 sourceId + targetId 标识);SINGLE_PER_LABEL 表示每个边标签在一对顶点之间可以有一条边(通过 sourceId + edgeLabel + targetId 标识);MULTIPLE 表示一对顶点之间可以存在多条边(通过 sourceId + edgeLabel + sortValues + targetId 标识)。
input.max_edges_in_one_vertex200允许附加到一个顶点的最大邻接边数量。邻接边将作为一个批处理单元一起存储和传输。

3.4 输入性能

配置项默认值说明
input.send_thread_nums4并行发送顶点或边的线程数量。

4. 快照与存储配置

HugeGraph-Computer 支持快照功能,可将顶点/边分区保存到本地存储或 MinIO 对象存储,用于断点恢复或加速重复计算。

4.1 基础快照配置

配置项默认值说明
snapshot.writefalse是否写入输入顶点/边分区的快照。
snapshot.loadfalse是否从顶点/边分区的快照加载。
snapshot.name"" (空)用户自定义的快照名称,用于区分不同的快照。

4.2 MinIO 集成(可选)

MinIO 可用作 K8s 部署中快照的分布式对象存储后端。

配置项默认值说明
snapshot.minio_endpoint"" (空)MinIO 服务端点(例如 http://minio:9000)。使用 MinIO 时必填。
snapshot.minio_access_keyminioadminMinIO 认证访问密钥。
snapshot.minio_secret_keyminioadminMinIO 认证密钥。
snapshot.minio_bucket_name"" (空)用于存储快照数据的 MinIO 存储桶名称。

使用场景:

  • 断点恢复:作业失败后从快照恢复,避免重新加载数据
  • 重复计算:多次运行同一算法时从快照加载数据以加速启动
  • A/B 测试:保存同一数据集的多个快照版本,测试不同的算法参数

示例:本地快照(在 computer.properties 中):

1snapshot.write=true
2snapshot.name=pagerank-snapshot-20260201

示例:MinIO 快照(在 K8s CRD computerConf 中):

1computerConf:
2  snapshot.write: "true"
3  snapshot.name: "pagerank-snapshot-v1"
4  snapshot.minio_endpoint: "http://minio:9000"
5  snapshot.minio_access_key: "my-access-key"
6  snapshot.minio_secret_key: "my-secret-key"
7  snapshot.minio_bucket_name: "hugegraph-snapshots"

5. Worker 与 Master 配置

Worker 和 Master 计算逻辑的配置。

5.1 Master 配置

配置项默认值说明
master.computation_classorg.apache.hugegraph.computer.core.master.DefaultMasterComputationMaster 计算是可以决定是否继续下一个超步的计算。它在每个超步结束时在 master 上运行。

5.2 Worker 计算

配置项默认值说明
worker.computation_classorg.apache.hugegraph.computer.core.config.Null创建 worker 计算对象的类。Worker 计算用于在每个超步中计算每个顶点。
worker.combiner_classorg.apache.hugegraph.computer.core.config.NullCombiner 可以将消息组合为一个顶点的一个值。例如,PageRank 算法可以将一个顶点的消息组合为一个求和值。
worker.partitionerorg.apache.hugegraph.computer.core.graph.partition.HashPartitioner分区器,决定顶点应该在哪个分区中,以及分区应该在哪个 worker 中。

5.3 Worker 组合器

配置项默认值说明
worker.vertex_properties_combiner_classorg.apache.hugegraph.computer.core.combiner.OverwritePropertiesCombiner组合器可以在输入步骤将同一顶点的多个属性组合为一个属性。
worker.edge_properties_combiner_classorg.apache.hugegraph.computer.core.combiner.OverwritePropertiesCombiner组合器可以在输入步骤将同一边的多个属性组合为一个属性。

5.4 Worker 缓冲区

配置项默认值说明
worker.received_buffers_bytes_limit104857600 (100 MB)接收数据缓冲区的限制字节数。所有缓冲区的总大小不能超过此限制。如果接收缓冲区达到此限制,它们将被合并到文件中(溢出到磁盘)。
worker.write_buffer_capacity52428800 (50 MB)用于存储顶点或消息的写缓冲区的初始大小。
worker.write_buffer_threshold52428800 (50 MB)写缓冲区的阈值。超过它将触发排序。写缓冲区用于存储顶点或消息。

5.5 Worker 数据与超时

配置项默认值说明
worker.data_dirs[jobs]用逗号分隔的目录,接收的顶点和消息可以持久化到其中。
worker.wait_sort_timeout600000 (10 分钟)消息处理程序等待排序线程对一批缓冲区进行排序的最大超时时间(毫秒)。
worker.wait_finish_messages_timeout86400000 (24 小时)消息处理程序等待所有 worker 完成消息的最大超时时间(毫秒)。

6. I/O 与输出配置

输出计算结果的配置。

6.1 输出类与结果

配置项默认值说明
output.output_classorg.apache.hugegraph.computer.core.output.LogOutput输出每个顶点计算结果的类。在迭代计算后调用。
output.result_namevalue该值由 WORKER_COMPUTATION_CLASS 创建的实例的 #name() 动态分配。
output.result_write_typeOLAP_COMMON输出到 HugeGraph 的结果写入类型,允许值:[OLAP_COMMON, OLAP_SECONDARY, OLAP_RANGE]。

6.2 输出行为

配置项默认值说明
output.with_adjacent_edgesfalse是否输出顶点的邻接边。
output.with_vertex_propertiesfalse是否输出顶点的属性。
output.with_edge_propertiesfalse是否输出边的属性。

6.3 批量输出

配置项默认值说明
output.batch_size500输出的批处理大小。
output.batch_threads1用于批量输出的线程数量。
output.single_threads1用于单个输出的线程数量。

6.4 HDFS 输出

配置项默认值说明
output.hdfs_urlhdfs://127.0.0.1:9000输出的 HDFS URL。
output.hdfs_userhadoop输出的 HDFS 用户。
output.hdfs_path_prefix/hugegraph-computer/resultsHDFS 输出结果的目录。
output.hdfs_delimiter, (逗号)HDFS 输出的分隔符。
output.hdfs_merge_partitionstrue是否合并多个分区的输出文件。
output.hdfs_replication3HDFS 的副本数。
output.hdfs_core_site_path"" (空)HDFS core site 路径。
output.hdfs_site_path"" (空)HDFS site 路径。
output.hdfs_kerberos_enablefalse是否为 HDFS 启用 Kerberos 认证。
output.hdfs_kerberos_principal"" (空)HDFS 的 Kerberos 认证 principal。
output.hdfs_kerberos_keytab"" (空)HDFS 的 Kerberos 认证 keytab 文件。
output.hdfs_krb5_conf/etc/krb5.confKerberos 配置文件路径。

6.5 重试与超时

配置项默认值说明
output.retry_times3输出失败时的重试次数。
output.retry_interval10输出失败时的重试间隔(秒)。
output.thread_pool_shutdown_timeout60输出线程池关闭的超时时间(秒)。

7. 网络与传输配置

Worker 和 Master 之间网络通信的配置。

7.1 服务器配置

配置项默认值说明
transport.server_host127.0.0.1worker 数据服务监听并向其他 worker 公告的地址。多主机场景必须使用其他节点可达的地址;Operator 会改为 Pod IP。
transport.server_port0(发行包:0;K8s Operator:8099)worker 数据传输监听端口。单机值 0 表示系统分配端口;Operator 会将 K8s 默认值改为固定端口 8099,以便 Pod 间通信。
transport.server_threads4服务器传输线程的数量。

7.2 客户端配置

配置项默认值说明
transport.client_threads4客户端传输线程的数量。
transport.client_connect_timeout3000客户端连接到服务器的超时时间(毫秒)。

7.3 协议配置

配置项默认值说明
transport.provider_classorg.apache.hugegraph.computer.core.network.netty.NettyTransportProvider传输提供程序,目前仅支持 Netty。
transport.io_modeAUTO网络 IO 模式,允许值:[NIO, EPOLL, AUTO]。AUTO 表示自动选择适当的模式。
transport.tcp_keep_alivetrue是否启用 TCP keep-alive。
transport.transport_epoll_ltfalse是否启用 EPOLL 水平触发(仅在 io_mode=EPOLL 时有效)。

7.4 缓冲区配置

配置项默认值说明
transport.send_buffer_size0Socket 发送缓冲区大小(字节)。0 表示使用系统默认值。
transport.receive_buffer_size0Socket 接收缓冲区大小(字节)。0 表示使用系统默认值。
transport.write_buffer_high_mark67108864 (64 MB)写缓冲区的高水位标记(字节)。如果排队字节数 > write_buffer_high_mark,将触发发送不可用。
transport.write_buffer_low_mark33554432 (32 MB)写缓冲区的低水位标记(字节)。如果排队字节数 < write_buffer_low_mark,将触发发送可用。

7.5 流量控制

配置项默认值说明
transport.max_pending_requests8客户端未接收 ACK 的最大数量。如果未接收 ACK 的数量 >= max_pending_requests,将触发发送不可用。
transport.min_pending_requests6客户端未接收 ACK 的最小数量。如果未接收 ACK 的数量 < min_pending_requests,将触发发送可用。
transport.min_ack_interval200服务器回复 ACK 的最小间隔(毫秒)。

7.6 超时配置

配置项默认值说明
transport.close_timeout10000关闭服务器或关闭客户端的超时时间(毫秒)。
transport.sync_request_timeout10000发送同步请求后等待响应的超时时间(毫秒)。
transport.finish_session_timeout0完成会话的超时时间(毫秒)。0 表示使用 (transport.sync_request_timeout × transport.max_pending_requests)。
transport.write_socket_timeout3000将数据写入 socket 缓冲区的超时时间(毫秒)。
transport.server_idle_timeout360000 (6 分钟)服务器空闲的最大超时时间(毫秒)。

7.7 心跳配置

配置项默认值说明
transport.heartbeat_interval20000 (20 秒)客户端心跳之间的最小间隔(毫秒)。
transport.max_timeout_heartbeat_count120客户端超时心跳的最大次数。如果连续等待心跳响应超时的次数 > max_timeout_heartbeat_count,通道将从客户端关闭。

7.8 高级网络设置

配置项默认值说明
transport.max_syn_backlog511服务器端 SYN 队列的容量。0 表示使用系统默认值。
transport.recv_file_modetrue是否启用接收缓冲文件模式。如果启用,将使用零拷贝从 socket 接收缓冲区并写入文件。注意:需要操作系统支持零拷贝(例如 Linux sendfile/splice)。
transport.network_retries3网络通信不稳定时的重试次数。

7.9 Master RPC 配置

以下两个键由 HugeGraph Commons 的 RPC 配置定义;computer.properties 发行模板显式设置了主机和端口。Kubernetes Operator 会公告 Pod IP,并在未指定有效端口时使用 8190。

配置项发行包值说明
rpc.server_host127.0.0.1(K8s:Pod IP)Master RPC 服务地址,worker 必须能访问此地址。
rpc.server_port8190(K8s 默认:8190)Master RPC 监听端口;集群安全组和网络策略须允许 worker 连接。

8. 存储与持久化配置

HGKV(HugeGraph Key-Value)存储引擎和值文件的配置。

8.1 HGKV 配置

配置项默认值说明
hgkv.max_file_size2147483648 (2 GB)每个 HGKV 文件的最大字节数。
hgkv.max_data_block_size65536 (64 KB)HGKV 文件数据块的最大字节大小。
hgkv.max_merge_files10一次合并的最大文件数。
hgkv.temp_file_dir/tmp/hgkv此文件夹用于在文件合并过程中存储临时文件。

8.2 值文件配置

配置项默认值说明
valuefile.max_segment_size1073741824 (1 GB)值文件每个段的最大字节数。

9. BSP 与协调配置

批量同步并行(BSP)协议和 etcd 协调的配置。

配置项默认值说明
bsp.etcd_endpointshttp://localhost:2379(发行包:http://127.0.0.1:2379)etcd 客户端端点;多个地址用逗号分隔。K8s Operator 在未由 computerConf 指定时使用 Operator 的 INTERNAL_ETCD_URL。
bsp.max_super_step10 (打包: 2)算法的最大超步数。
bsp.register_timeout300000 (打包: 100000)等待 master 和 worker 注册的最大超时时间(毫秒)。
bsp.wait_workers_timeout86400000 (24 小时)等待 worker BSP 事件的最大超时时间(毫秒)。
bsp.wait_master_timeout86400000 (24 小时)等待 master BSP 事件的最大超时时间(毫秒)。
bsp.log_interval30000 (30 秒)等待 BSP 事件时打印日志的日志间隔(毫秒)。

10. 性能调优配置

性能优化的配置。

配置项默认值说明
allocator.max_vertices_per_thread10000每个内存分配器中每个线程处理的最大顶点数。
sort.thread_nums4执行内部排序的线程数量。

11. 系统管理配置

以下配置在 Kubernetes 作业中由 Operator 自动补齐或覆盖。除非自定义了 Operator 或网络,不应手动覆盖这些值;job.namespace 是可选的用户配置,见基础配置表。

配置项管理者说明
bsp.etcd_endpointsK8s Operator仅在 computerConf 未设置时,取 Operator 的 INTERNAL_ETCD_URL。
transport.server_hostK8s Operator覆盖为 Pod IP;worker 需要互相访问。
transport.server_portK8s Operator未设置或为 0 时设置为 8099,不是随机端口。
job.idK8s Operator自动从 CRD 设置为作业 ID
job.workers_countK8s Operator自动从 CRD workerInstances 设置
rpc.server_hostK8s Operator覆盖为 master Pod IP。
rpc.server_portK8s Operator未设置或为 0 时设置为 8190。
rpc.remote_urlComputer 启动流程读取配置时会移除该项,不应作为作业配置设置。

为什么禁止修改:

  • BSP/RPC 配置:必须与实际部署的 etcd/RPC 服务匹配。手动覆盖会破坏协调。
  • 作业配置:必须与 K8s CRD 规范匹配。不匹配会导致 worker 数量错误。
  • 传输配置:必须使用 worker 互相可达的 Pod IP 和端口;K8s 的默认端口为 8099。

K8s Operator 配置选项

注意:选项需要通过环境变量设置进行转换,例如 k8s.internal_etcd_url => INTERNAL_ETCD_URL

配置项默认值说明
k8s.auto_destroy_podtrue作业完成或失败后是否删除作业 CR;CR 删除后 Operator 会清理关联计算资源。
k8s.close_reconciler_timeout120关闭 reconciler 的最大超时时间(毫秒)。
k8s.internal_etcd_url代码默认 http://127.0.0.1:2379;发行清单覆盖为 http://hugegraph-computer-operator-etcd.hugegraph-computer-operator-system:2379Operator 作业使用的 etcd URL。使用随附清单时实际值是 etcd Service 地址。
k8s.internal_minio_url代码默认 http://127.0.0.1:9000;发行清单覆盖为 http://hugegraph-computer-operator-minio.hugegraph-computer-operator-system:9000Operator 为作业补入的 MinIO 地址;仅启用 MinIO 快照时需要。
k8s.max_reconcile_retry3reconcile 的最大重试次数。
k8s.probe_backlog50服务健康探针的最大积压。
k8s.probe_port9892controller 绑定的用于服务健康探针的端口。
k8s.ready_check_internal1000检查就绪的时间间隔(毫秒)。
k8s.ready_timeout30000检查就绪的最大超时时间(毫秒)。
k8s.reconciler_count代码默认 Runtime.getRuntime().availableProcessors();发行清单覆盖为 6reconciler 线程的最大数量。
k8s.resync_period600000被监视资源进行 reconcile 的最小频率。
k8s.timezoneAsia/Shanghaicomputer 作业和 operator 的时区。
k8s.watch_namespacehugegraph-computer-operator-system监视自定义资源的命名空间。随附发行清单也设置为此值;使用 * 可监视所有命名空间。

HugeGraph-Computer CRD

1.7.0 CRD: https://github.com/apache/hugegraph-computer/blob/1.7.0/computer/computer-k8s-operator/manifest/hugegraph-computer-crd.v1.yaml

字段默认值说明必填
algorithmName算法名称。true
jobId作业 ID。true
imageComputer 作业使用的容器镜像,必须包含 Computer 运行时。目标算法 JAR 可预置在镜像内,或通过 remoteJarUri 下载。true
computerConfcomputer 配置选项的映射。true
workerInstancesworker 实例数量,将覆盖 ‘job.workers_count’ 选项。true
pullPolicy未设置时由 Kubernetes 按镜像标签决定:latest 为 Always,其他标签为 IfNotPresent可显式设置 Always、Never 或 IfNotPresent;CRD 未提供默认值。详见 镜像拉取策略。false
pullSecrets镜像拉取密钥,详情请参考:https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-podfalse
masterCpumaster 的 CPU 限制,单位可以是 ’m’ 或无单位,详情请参考:https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpufalse
workerCpuworker 的 CPU 限制,单位可以是 ’m’ 或无单位,详情请参考:https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-cpufalse
masterMemorymaster 的内存限制,单位可以是 Ei、Pi、Ti、Gi、Mi、Ki 之一,详情请参考:https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memoryfalse
workerMemoryworker 的内存限制,单位可以是 Ei、Pi、Ti、Gi、Mi、Ki 之一,详情请参考:https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#meaning-of-memoryfalse
log4jXmlcomputer 作业的 log4j.xml 内容。false
jarFile容器镜像内算法 JAR 的路径。false
remoteJarUri算法 JAR 的 HTTP(S) 地址;启动脚本会下载该 JAR 并加载。false
jvmOptionscomputer 作业的 Java 启动参数。false
envVars请参考:https://kubernetes.io/docs/tasks/inject-data-application/define-interdependent-environment-variables/false
envFrom请参考:https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/false
masterCommandbin/start-computer.shmaster 的运行命令,等同于 Docker 的 ‘Entrypoint’ 字段。false
masterArgs["-r master", “-d k8s”]master 的运行参数,等同于 Docker 的 ‘Cmd’ 字段。false
workerCommandbin/start-computer.shworker 的运行命令,等同于 Docker 的 ‘Entrypoint’ 字段。false
workerArgs["-r worker", “-d k8s”]worker 的运行参数,等同于 Docker 的 ‘Cmd’ 字段。false
volumes请参考:https://kubernetes.io/docs/concepts/storage/volumes/false
volumeMounts请参考:https://kubernetes.io/docs/concepts/storage/volumes/false
secretPathsk8s-secret 名称和挂载路径的映射。false
configMapPathsk8s-configmap 名称和挂载路径的映射。false
podTemplateSpec请参考:https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-template-v1/#PodTemplateSpecfalse
securityContext请参考:https://kubernetes.io/docs/tasks/configure-pod-container/security-context/false

KubeDriver 配置选项

配置项默认值说明
k8s.build_image_bash_path用于构建镜像的命令路径。
k8s.enable_internal_algorithmtrue是否启用内部算法。
k8s.framework_image_urlhugegraph/hugegraph-computer:latestcomputer 框架的镜像 URL。
k8s.image_repository_password登录镜像仓库的密码。
k8s.image_repository_registry登录镜像仓库的地址。
k8s.image_repository_urlhugegraph/hugegraph-computer镜像仓库的 URL。
k8s.image_repository_username登录镜像仓库的用户名。
k8s.internal_algorithm[pageRank]所有内部算法的名称列表。注意:算法名称在这里使用驼峰命名法(例如 pageRank),但算法实现返回下划线命名法(例如 page_rank)。
k8s.internal_algorithm_image_urlhugegraph/hugegraph-computer:latest内部算法的镜像 URL。
k8s.jar_file_dir/cache/jars/算法 jar 将上传到的目录。
k8s.kube_config~/.kube/configk8s 配置文件的路径。
k8s.log4j_xml_pathcomputer 作业的 log4j.xml 路径。
k8s.namespacehugegraph-computer-operator-systemhugegraph-computer 系统的命名空间。
k8s.pull_secret_names[]拉取镜像的 pull-secret 名称。

5 - HugeGraph Client

Java 和 Go Client 位于 HugeGraph Toolchain 仓库,Python Client 位于 HugeGraph-AI 仓库。三者的安装方式和 API 不完全相同,请进入对应页面查看。

5.1 - HugeGraph-Java-Client

1 HugeGraph-Client 概述

HugeGraph Java Client 将 Java API 转换为 HugeGraph Server 的 REST 请求,支持管理 Schema 和图数据、执行 Gremlin 及调用 Traverser API。详细接口见 Client API,本文给出 Java 项目的接入示例。

其他语言可使用 Go Client 或 HugeGraph-AI 仓库中的 Python Client。

2 环境要求

  • JDK 17,用于本文示例及从 Toolchain master 构建 Client 1.8.0
  • Maven 3.6.3+

3 使用流程

按下面的顺序接入 HugeGraph-Client。

  1. 使用 IntelliJ IDEA 或 Eclipse 新建 Maven 工程。
  2. 在 pom.xml 中添加 HugeGraph-Client 依赖。
  3. 创建客户端、调用 API,并在使用后关闭客户端。

详细操作见下面的完整示例。

4 完整示例

4.1 新建 Maven 工程

使用 Eclipse 或 IntelliJ IDEA 创建 Maven 工程。

4.2 添加 hugegraph-client 依赖

在 pom.xml 中添加依赖。

1
2<dependencies>
3    <dependency>
4        <groupId>org.apache.hugegraph</groupId>
5        <artifactId>hugegraph-client</artifactId>
6        <!-- 以下完整示例可使用已发布的 1.7.0 -->
7        <version>1.7.0</version>
8    </dependency>
9</dependencies>

先根据用途选择客户端版本。

用途客户端版本Java 编译目标
运行下方完整示例已发布的 1.7.0,使用上面的依赖即可发布版 POM 为 Java 8;本文统一使用 JDK 17
使用能力探测等 master 新接口Toolchain master(以 1.8 为基线)Java 17

示例使用的 Schema、Graph、Gremlin 和资源关闭接口在 Client 1.7.0 中可用,也与 Toolchain master 兼容。 发布版的 Java 编译目标不代表所有传递依赖的运行环境要求。

若需要使用 master 分支未发布的新接口,可从源码编译安装 Client(需配合 Toolchain 源码,详见 Tools 源码构建指引):

1java -version
2mvn -version
3mvn -Dmaven.repo.local="${candidate_dir:?Run the candidate SDK setup first}/m2" \
4  -Dsdk.validation.mode=candidate \
5  install -pl hugegraph-client -am -DskipTests -Dmaven.javadoc.skip=true -ntp

两条版本检查都应显示 JDK 17。使用 master 分支 Client 的项目运行 Maven 命令时,也需添加 -Dmaven.repo.local="$candidate_dir/m2"。 Client 与 Server 的版本不必相同;升级前核对所需 API 及兼容范围。

4.3 Example

选择单条操作或批量操作示例,将完整代码保存为 Maven 工程中的 src/main/java/SingleExample.java 或 src/main/java/BatchExample.java。复制按钮会包含已折叠的代码行。

4.3.1 SingleExample
  1import java.io.IOException;
  2import java.util.Iterator;
  3import java.util.List;
  4
  5import org.apache.hugegraph.driver.GraphManager;
  6import org.apache.hugegraph.driver.GremlinManager;
  7import org.apache.hugegraph.driver.HugeClient;
  8import org.apache.hugegraph.driver.SchemaManager;
  9import org.apache.hugegraph.structure.constant.T;
 10import org.apache.hugegraph.structure.graph.Edge;
 11import org.apache.hugegraph.structure.graph.Path;
 12import org.apache.hugegraph.structure.graph.Vertex;
 13import org.apache.hugegraph.structure.gremlin.Result;
 14import org.apache.hugegraph.structure.gremlin.ResultSet;
 15
 16public class SingleExample {
 17
 18    public static void main(String[] args) throws IOException {
 19        // If connect failed will throw a exception.
 20        HugeClient hugeClient = HugeClient.builder("http://localhost:8080",
 21                                                   "DEFAULT",
 22                                                   "hugegraph")
 23                                          .configUser("username", "password")
 24                                          // 这是示例,生产环境需要使用安全的凭证
 25                                          .build();
 26
 27        SchemaManager schema = hugeClient.schema();
 28
 29        schema.propertyKey("name").asText().ifNotExist().create();
 30        schema.propertyKey("age").asInt().ifNotExist().create();
 31        schema.propertyKey("city").asText().ifNotExist().create();
 32        schema.propertyKey("weight").asDouble().ifNotExist().create();
 33        schema.propertyKey("lang").asText().ifNotExist().create();
 34        schema.propertyKey("date").asDate().ifNotExist().create();
 35        schema.propertyKey("price").asInt().ifNotExist().create();
 36
 37        schema.vertexLabel("person")
 38              .properties("name", "age", "city")
 39              .primaryKeys("name")
 40              .ifNotExist()
 41              .create();
 42
 43        schema.vertexLabel("software")
 44              .properties("name", "lang", "price")
 45              .primaryKeys("name")
 46              .ifNotExist()
 47              .create();
 48
 49        schema.indexLabel("personByCity")
 50              .onV("person")
 51              .by("city")
 52              .secondary()
 53              .ifNotExist()
 54              .create();
 55
 56        schema.indexLabel("personByAgeAndCity")
 57              .onV("person")
 58              .by("age", "city")
 59              .secondary()
 60              .ifNotExist()
 61              .create();
 62
 63        schema.indexLabel("softwareByPrice")
 64              .onV("software")
 65              .by("price")
 66              .range()
 67              .ifNotExist()
 68              .create();
 69
 70        schema.edgeLabel("knows")
 71              .sourceLabel("person")
 72              .targetLabel("person")
 73              .properties("date", "weight")
 74              .ifNotExist()
 75              .create();
 76
 77        schema.edgeLabel("created")
 78              .sourceLabel("person").targetLabel("software")
 79              .properties("date", "weight")
 80              .ifNotExist()
 81              .create();
 82
 83        schema.indexLabel("createdByDate")
 84              .onE("created")
 85              .by("date")
 86              .secondary()
 87              .ifNotExist()
 88              .create();
 89
 90        schema.indexLabel("createdByWeight")
 91              .onE("created")
 92              .by("weight")
 93              .range()
 94              .ifNotExist()
 95              .create();
 96
 97        schema.indexLabel("knowsByWeight")
 98              .onE("knows")
 99              .by("weight")
100              .range()
101              .ifNotExist()
102              .create();
103
104        GraphManager graph = hugeClient.graph();
105        Vertex marko = graph.addVertex(T.LABEL, "person", "name", "marko",
106                                       "age", 29, "city", "Beijing");
107        Vertex vadas = graph.addVertex(T.LABEL, "person", "name", "vadas",
108                                       "age", 27, "city", "Hongkong");
109        Vertex lop = graph.addVertex(T.LABEL, "software", "name", "lop",
110                                     "lang", "java", "price", 328);
111        Vertex josh = graph.addVertex(T.LABEL, "person", "name", "josh",
112                                      "age", 32, "city", "Beijing");
113        Vertex ripple = graph.addVertex(T.LABEL, "software", "name", "ripple",
114                                        "lang", "java", "price", 199);
115        Vertex peter = graph.addVertex(T.LABEL, "person", "name", "peter",
116                                       "age", 35, "city", "Shanghai");
117
118        marko.addEdge("knows", vadas, "date", "2016-01-10", "weight", 0.5);
119        marko.addEdge("knows", josh, "date", "2013-02-20", "weight", 1.0);
120        marko.addEdge("created", lop, "date", "2017-12-10", "weight", 0.4);
121        josh.addEdge("created", lop, "date", "2009-11-11", "weight", 0.4);
122        josh.addEdge("created", ripple, "date", "2017-12-10", "weight", 1.0);
123        peter.addEdge("created", lop, "date", "2017-03-24", "weight", 0.2);
124
125        GremlinManager gremlin = hugeClient.gremlin();
126        System.out.println("==== Path ====");
127        ResultSet resultSet = gremlin.gremlin("g.V().outE().path()").execute();
128        Iterator<Result> results = resultSet.iterator();
129        results.forEachRemaining(result -> {
130            System.out.println(result.getObject().getClass());
131            Object object = result.getObject();
132            if (object instanceof Vertex) {
133                System.out.println(((Vertex) object).id());
134            } else if (object instanceof Edge) {
135                System.out.println(((Edge) object).id());
136            } else if (object instanceof Path) {
137                List<Object> elements = ((Path) object).objects();
138                elements.forEach(element -> {
139                    System.out.println(element.getClass());
140                    System.out.println(element);
141                });
142            } else {
143                System.out.println(object);
144            }
145        });
146
147        hugeClient.close();
148    }
149}
4.3.2 BatchExample
  1import java.util.ArrayList;
  2import java.util.List;
  3
  4import org.apache.hugegraph.driver.GraphManager;
  5import org.apache.hugegraph.driver.HugeClient;
  6import org.apache.hugegraph.driver.SchemaManager;
  7import org.apache.hugegraph.structure.graph.Edge;
  8import org.apache.hugegraph.structure.graph.Vertex;
  9
 10public class BatchExample {
 11
 12    public static void main(String[] args) {
 13        // If connect failed will throw a exception.
 14        HugeClient hugeClient = HugeClient.builder("http://localhost:8080",
 15                                                "DEFAULT",
 16                                                "hugegraph")
 17                                          .configUser("username", "password")
 18                                          // 这是示例,生产环境需要使用安全的凭证
 19                                          .build();
 20
 21        SchemaManager schema = hugeClient.schema();
 22
 23        schema.propertyKey("name").asText().ifNotExist().create();
 24        schema.propertyKey("age").asInt().ifNotExist().create();
 25        schema.propertyKey("lang").asText().ifNotExist().create();
 26        schema.propertyKey("date").asDate().ifNotExist().create();
 27        schema.propertyKey("price").asInt().ifNotExist().create();
 28
 29        schema.vertexLabel("person")
 30              .properties("name", "age")
 31              .primaryKeys("name")
 32              .ifNotExist()
 33              .create();
 34
 35        schema.vertexLabel("person")
 36              .properties("price")
 37              .nullableKeys("price")
 38              .append();
 39
 40        schema.vertexLabel("software")
 41              .properties("name", "lang", "price")
 42              .primaryKeys("name")
 43              .ifNotExist()
 44              .create();
 45
 46        schema.indexLabel("softwareByPrice")
 47              .onV("software").by("price")
 48              .range()
 49              .ifNotExist()
 50              .create();
 51
 52        schema.edgeLabel("knows")
 53              .link("person", "person")
 54              .properties("date")
 55              .ifNotExist()
 56              .create();
 57
 58        schema.edgeLabel("created")
 59              .link("person", "software")
 60              .properties("date")
 61              .ifNotExist()
 62              .create();
 63
 64        schema.indexLabel("createdByDate")
 65              .onE("created").by("date")
 66              .secondary()
 67              .ifNotExist()
 68              .create();
 69
 70        // get schema object by name
 71        System.out.println(schema.getPropertyKey("name"));
 72        System.out.println(schema.getVertexLabel("person"));
 73        System.out.println(schema.getEdgeLabel("knows"));
 74        System.out.println(schema.getIndexLabel("createdByDate"));
 75
 76        // list all schema objects
 77        System.out.println(schema.getPropertyKeys());
 78        System.out.println(schema.getVertexLabels());
 79        System.out.println(schema.getEdgeLabels());
 80        System.out.println(schema.getIndexLabels());
 81
 82        GraphManager graph = hugeClient.graph();
 83
 84        Vertex marko = new Vertex("person").property("name", "marko")
 85                                           .property("age", 29);
 86        Vertex vadas = new Vertex("person").property("name", "vadas")
 87                                           .property("age", 27);
 88        Vertex lop = new Vertex("software").property("name", "lop")
 89                                           .property("lang", "java")
 90                                           .property("price", 328);
 91        Vertex josh = new Vertex("person").property("name", "josh")
 92                                          .property("age", 32);
 93        Vertex ripple = new Vertex("software").property("name", "ripple")
 94                                              .property("lang", "java")
 95                                              .property("price", 199);
 96        Vertex peter = new Vertex("person").property("name", "peter")
 97                                           .property("age", 35);
 98
 99        Edge markoKnowsVadas = new Edge("knows").source(marko).target(vadas)
100                                                .property("date", "2016-01-10");
101        Edge markoKnowsJosh = new Edge("knows").source(marko).target(josh)
102                                               .property("date", "2013-02-20");
103        Edge markoCreateLop = new Edge("created").source(marko).target(lop)
104                                                 .property("date",
105                                                           "2017-12-10");
106        Edge joshCreateRipple = new Edge("created").source(josh).target(ripple)
107                                                   .property("date",
108                                                             "2017-12-10");
109        Edge joshCreateLop = new Edge("created").source(josh).target(lop)
110                                                .property("date", "2009-11-11");
111        Edge peterCreateLop = new Edge("created").source(peter).target(lop)
112                                                 .property("date",
113                                                           "2017-03-24");
114
115        List<Vertex> vertices = new ArrayList<>();
116        vertices.add(marko);
117        vertices.add(vadas);
118        vertices.add(lop);
119        vertices.add(josh);
120        vertices.add(ripple);
121        vertices.add(peter);
122
123        List<Edge> edges = new ArrayList<>();
124        edges.add(markoKnowsVadas);
125        edges.add(markoKnowsJosh);
126        edges.add(markoCreateLop);
127        edges.add(joshCreateRipple);
128        edges.add(joshCreateLop);
129        edges.add(peterCreateLop);
130
131        vertices = graph.addVertices(vertices);
132        vertices.forEach(vertex -> System.out.println(vertex));
133
134        edges = graph.addEdges(edges, false);
135        edges.forEach(edge -> System.out.println(edge));
136
137        hugeClient.close();
138    }
139}

4.4 运行 Example

  1. 启动 HugeGraph Server,在图空间 DEFAULT 中准备名为 hugegraph 的测试图。
  2. 将 Maven 工程的 JDK 设为 17,把所选示例中 HugeClient.builder(...) 和 configUser(...) 的 Server 地址、图空间、图名和凭据改为实际配置。 Server 未开启鉴权时,省略 configUser(...)。
  3. 在 IDE 中运行 SingleExample.main() 或 BatchExample.main()。两个示例都会创建 Schema 和图数据、打印结果并关闭客户端。 请使用测试图,已有 Schema 或数据可能影响重复运行。

4.5 详细 API 说明

示例说明见HugeGraph-Client 基本 API 介绍

5.2 - HugeGraph Python 客户端快速上手

hugegraph-python-client 是 HugeGraph 的 Python SDK,可管理 Schema、读写图数据并执行 Gremlin 查询。HugeGraph-LLM 和 HugeGraph-ML 也使用这个客户端。

该模块位于 hugegraph-ai 仓库的 hugegraph-python-client/ 目录下,导入名为 pyhugegraph。

环境要求

  • 客户端与 HugeGraph-AI workspace 均要求 Python 3.10 或更高版本,CI 在 3.10 和 3.11 上运行客户端测试。
  • HugeGraph Server 1.5.0 或更高版本。客户端会拒绝连接更低版本的 Server,此类场景请改用 v1.3.x 客户端。
  • uv(推荐)或 pip

运行时依赖为 decorator、requests、setuptools、urllib3 和 rich。

安装

发布到 PyPI 的发行包名是 hugegraph-python:

1uv pip install hugegraph-python
2# 也可以使用 pip install hugegraph-python

上述命令不固定版本号,默认安装最新发布版;发行信息见 PyPI 发布页。源码目录名是 hugegraph-python-client,发行包名为 hugegraph-python;需要主线代码时,请从 HugeGraph-AI workspace 安装。

如需使用仓库中的最新代码,请从 HugeGraph-AI 仓库根目录同步 workspace。hugegraph-python-client 是 workspace 成员,通过 python-client extra 暴露,因此仅执行 uv sync 不会安装它:

1git clone https://github.com/apache/hugegraph-ai.git
2cd hugegraph-ai
3uv sync --extra python-client
4source .venv/bin/activate

连接并写入数据

 1from pyhugegraph.client import PyHugeClient
 2
 3client = PyHugeClient(
 4    url="http://127.0.0.1:8080",
 5    graph="hugegraph",
 6    user="admin",
 7    pwd="admin",
 8    graphspace=None,
 9)
10
11schema = client.schema()
12schema.propertyKey("name").asText().ifNotExist().create()
13schema.propertyKey("birthDate").asText().ifNotExist().create()
14schema.vertexLabel("Person").properties("name", "birthDate") \
15      .usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
16schema.vertexLabel("Movie").properties("name") \
17      .usePrimaryKeyId().primaryKeys("name").ifNotExist().create()
18schema.edgeLabel("ActedIn").sourceLabel("Person").targetLabel("Movie") \
19      .ifNotExist().create()
20
21graph = client.graph()
22person = graph.addVertex(
23    "Person", {"name": "Al Pacino", "birthDate": "1940-04-25"}
24)
25movie = graph.addVertex("Movie", {"name": "The Godfather"})
26edge = graph.addEdge("ActedIn", person.id, movie.id, {})
27
28print(graph.getVertexById(person.id))
29print(graph.getEdgeById(edge.id))
30graph.close()

客户端参数

PyHugeClient(url, graph, user, pwd, graphspace=None, timeout=None)

参数类型默认值说明
urlstr必填HugeGraph Server 的基础 URL。若未带协议头,客户端会自动补上 http://,因此 127.0.0.1:8080 也可以使用。
graphstr必填图名称,是第二个位置参数。
userstr必填用户名,以 HTTP Basic Auth 发送。
pwdstr必填密码,以 HTTP Basic Auth 发送。
graphspacestr 或 NoneNoneGraphSpace 名称,None 的解析规则见下文。
timeouttuple[float, float] 或 NoneNone(连接, 读取) 超时时间,单位为秒。None 会取 (0.5, 15.0)。

每个 HTTP 会话在收到 500、502、504 响应时会重试 3 次,退避因子为 0.1。

Server 版本与 GraphSpace

客户端在构造时解析 GraphSpace:

  • 传入非空的 graphspace 字符串时直接开启 GraphSpace 模式。
  • 否则客户端会请求 GET {url}/versions 并读取 versions.core。
  • Server 版本低于 1.5.0 时抛出 RuntimeError,提示升级 Server 或改用 v1.3.x 客户端。
  • Server 版本高于 1.5.0 时会把 graphspace 设为 DEFAULT 并开启 GraphSpace 模式,同时在日志中打印警告。版本恰好为 1.5.0 时保持关闭。
  • 若因网络原因探测失败,GraphSpace 模式保持关闭。

该模式决定请求前缀:开启时为 /graphspaces/<graphspace>/graphs/<graph>/...,关闭时为 /graphs/<graph>/...。

客户端提供的 Manager

每个访问器都会惰性创建对应的 Manager,并为其分配独立的 HTTP 会话。

访问器Manager覆盖范围
client.schema()SchemaManager属性、顶点标签、边标签、索引标签
client.graph()GraphManager顶点与边的增删改查、批量写入、分页
client.gremlin()GremlinManager执行 Gremlin
client.graphs()GraphsManager图列表、图信息、配置、清空数据
client.traverser()TraverserManager遍历与路径算法
client.variable()VariableManager图变量
client.task()TaskManager异步任务的查询、取消、删除
client.auth()AuthManager用户、用户组、资源、归属、权限
client.metrics()MetricsManagerServer 指标
client.version()VersionManagerServer 版本

pyhugegraph.api 中还提供了 RankManager、RebuildManager 和 ServicesManager,但 PyHugeClient 暂未提供对应的访问器,需要时可自行传入 session 构造。

常用操作

构建 Schema

Schema 构建器采用链式调用,最后调用 create(),也可以用 append()、eliminate() 和 remove() 修改已有定义。

 1schema = client.schema()
 2
 3# 属性类型:asText/asInt/asLong/asFloat/asDouble/asBool/asByte/asBlob/asDate/asObject
 4# 基数:valueSingle/valueList/valueSet
 5# 聚合:calcMax/calcMin/calcSum/calcOld
 6schema.propertyKey("age").asInt().valueSingle().ifNotExist().create()
 7
 8# 顶点标签 ID 策略:useAutomaticId/useCustomizeStringId/useCustomizeNumberId/usePrimaryKeyId
 9schema.vertexLabel("person").properties("name", "age", "city") \
10      .primaryKeys("name").nullableKeys("city").ifNotExist().create()
11
12# 边标签:link() 等价于 sourceLabel() 加 targetLabel()
13schema.edgeLabel("knows").link("person", "person").multiTimes() \
14      .properties("date", "city").sortKeys("date").nullableKeys("city") \
15      .ifNotExist().create()
16
17# 索引标签:先 onV/onE,再选择 secondary/range/search/shard/unique
18schema.indexLabel("personByCity").onV("person").by("city") \
19      .secondary().ifNotExist().create()

查询 Schema

 1schema = client.schema()
 2print(schema.getSchema())            # 完整 Schema,format 默认为 json
 3print(schema.getPropertyKeys())
 4print(schema.getVertexLabels())
 5print(schema.getEdgeLabels())
 6print(schema.getIndexLabels())
 7
 8# 查询单个定义
 9print(schema.getPropertyKey("name"))
10print(schema.getVertexLabel("person"))
11print(schema.getEdgeLabel("knows"))
12print(schema.getIndexLabel("personByCity"))
13
14# 边标签的连接关系,格式形如 Person--ActedIn-->Movie
15print(schema.getRelations())

读取、更新和删除图数据

图接口直接接收属性字典,不支持链式的属性构建器:

1graph = client.graph()
2graph.appendVertex(person.id, {"birthDate": "1940-04-25"})    # 追加属性
3graph.eliminateVertex(person.id, {"birthDate": "1940-04-25"}) # 删除属性
4graph.appendEdge(edge.id, {"city": "Beijing"})
5graph.eliminateEdge(edge.id, {"city": "Beijing"})
6graph.removeEdgeById(edge.id)
7graph.removeVertexById(person.id)
8graph.close()

addVertex 返回 VertexData,包含 id、label、type 和 properties。addEdge 返回 EdgeData,包含 id、label、type、outV、outVLabel、inV、inVLabel 和 properties。

传给客户端的顶点 ID 可以是字符串、整数或 uuid.UUID。布尔值会被拒绝,整数必须落在 Java signed long 范围内。

批量写入

addVertices 接收 (label, properties) 二元组,addEdges 接收 (label, out_id, in_id, out_label, in_label, properties) 六元组。两者返回的对象只携带生成的 ID。

1graph = client.graph()
2vertices = graph.addVertices([
3    ("person", {"name": "Alice", "age": 20}),
4    ("person", {"name": "Bob", "age": 23}),
5])
6edges = graph.addEdges([
7    ("knows", vertices[0].id, vertices[1].id, "person", "person", {"date": "2012-01-10"}),
8])

分页与条件查询

 1graph = client.graph()
 2
 3# 返回 (vertices, next_page),把 next_page 传回即可继续翻页
 4vertices, next_page = graph.getVertexByPage("person", limit=10)
 5vertices, next_page = graph.getVertexByPage("person", limit=10, page=next_page)
 6
 7# 服务端属性条件
 8older = graph.getVertexByCondition("person", properties={"age": "P.gt(29)"})
 9
10# 边分页查询,传入 vertex_id 时必须同时传 direction
11edges, next_page = graph.getEdgeByPage(label="knows", limit=10)
12edges, next_page = graph.getEdgeByPage(vertex_id=person.id, direction="OUT", limit=10)
13
14# 按 ID 批量查询
15graph.getVerticesById([v1.id, v2.id])
16graph.getEdgesById([e1.id, e2.id])

执行 Gremlin

1gremlin = client.gremlin()
2result = gremlin.exec("g.V().limit(5)")
3print(result)

exec 会根据图名称和解析出的 GraphSpace 自动绑定 graph 与 g 别名,并返回服务端响应中的 result 字段。响应缺少 requestId、status 或 result 时抛出 ResponseParseError。

图遍历

TraverserManager 封装了 Server 的 traverser 接口,方法名使用蛇形命名。

 1traverser = client.traverser()
 2
 3traverser.k_out(marko_id, 2)
 4traverser.k_neighbor(marko_id, 2)
 5traverser.same_neighbors(marko_id, josh_id)
 6traverser.jaccard_similarity(marko_id, josh_id)
 7traverser.shortest_path(marko_id, ripple_id, 3)
 8traverser.all_shortest_paths(marko_id, ripple_id, 3)
 9traverser.weighted_shortest_path(marko_id, ripple_id, "weight", 3)
10traverser.single_source_shortest_path(marko_id, 2)
11traverser.multi_node_shortest_path([marko_id, josh_id], max_depth=2)
12traverser.paths(marko_id, josh_id, 2)
13traverser.crosspoints(marko_id, josh_id, 2)
14traverser.rings(marko_id, 3)
15traverser.rays(marko_id, 2)
16traverser.vertices(marko_id)
17traverser.edges(edge_id)

基于 POST 的接口需要传入请求体:advanced_paths、customized_paths、template_paths、customized_crosspoints 和 fusiform_similarity。

图变量

1variable = client.variable()
2variable.set("owner", "mary")
3print(variable.get("owner"))
4print(variable.all())
5variable.remove("owner")

异步任务

1task = client.task()
2print(task.list_tasks(status="success", limit=10))
3print(task.get_task(task_id))
4task.cancel_task(task_id)
5task.delete_task(task_id)

Server 指标与图信息

 1metrics = client.metrics()
 2metrics.get_all_basic_metrics()
 3metrics.get_gauges_metrics()
 4metrics.get_counters_metrics()
 5metrics.get_histograms_metrics()
 6metrics.get_meters_metrics()
 7metrics.get_timers_metrics()
 8metrics.get_statistics_metrics()
 9metrics.get_system_metrics()
10metrics.get_backend_metrics()
11
12graphs = client.graphs()
13graphs.get_all_graphs()
14graphs.get_version()
15graphs.get_graph_info()
16graphs.get_graph_config()
17graphs.clear_graph_all_data()   # 删除全部顶点、边和 Schema
18
19print(client.version().version())

认证与授权

AuthManager 与 Server 的路由保持一致:用户、资源、归属和权限挂载在 /graphspaces/{graphspace}/auth/... 下,用户组仍在 Server 级别的 /auth/groups。在 HugeGraph 1.7.0 及以上版本必须能解析出 graphspace,否则这些调用会在发出请求前抛出 ValueError。

 1auth = client.auth()
 2
 3user = auth.create_user("test_user", "password")
 4auth.modify_user(user["id"], user_email="hugegraph@apache.org")
 5auth.get_user(user["id"])
 6auth.list_users(limit=10)
 7auth.delete_user(user["id"])
 8
 9group = auth.create_group("test_group", "read only")
10auth.modify_group(group["id"], group_description="updated")
11auth.list_groups()
12auth.delete_group(group["id"])
13
14target = auth.create_target("target1", "hugegraph", "127.0.0.1:8080", [])
15auth.update_target(target["id"], "target1", "hugegraph", "127.0.0.1:8080", [])
16auth.list_targets()
17auth.delete_target(target["id"])
18
19belong = auth.create_belong(user["id"], group["id"])
20auth.update_belong(belong["id"], "description")
21auth.list_belongs()
22auth.delete_belong(belong["id"])
23
24access = auth.grant_accesses(group["id"], target["id"], "READ")
25auth.modify_accesses(access["id"], "description")
26auth.list_accesses()
27auth.revoke_accesses(access["id"])

方法命名

Manager 中以驼峰命名的方法(例如 addVertex、getVertexById)会在构造时自动生成蛇形命名别名,graph.add_vertex(...) 与 graph.addVertex(...) 指向同一个方法。驼峰写法已在 debug 日志中标记为废弃,新代码建议使用蛇形命名。

错误处理

异常定义在 pyhugegraph.utils.exceptions 中:

异常触发条件
NotAuthorizedErrorServer 返回 401
NotFoundErrorServer 返回 404,或缺少必填参数
ServerError其他非 2xx 响应,异常信息中附带服务端消息
ResponseParseError成功响应无法解析为预期结构
ServiceUnavailableErrorServer 返回 ServiceUnavailableException
InvalidParameterError、CreateError、RemoveError、UpdateError、DataFormatError由各构建器和数据结构抛出

请求体与响应体写入日志时,会对密码、token 和 secret 等字段做脱敏处理。

1from pyhugegraph.utils.exceptions import NotFoundError
2
3try:
4    graph.getVertexById("no-such-id")
5except NotFoundError:
6    print("vertex missing")

接口参数会随 HugeGraph REST API 版本变化。遇到不兼容时,先核对当前 Server 的 REST API 文档与客户端测试用例。

开发检查

在 HugeGraph-AI 仓库根目录运行格式与静态检查:

1./style/code_format_and_analysis.sh

按照 CI 的方式运行测试:

1# 单元测试与契约测试,无需 Server
2uv run pytest hugegraph-python-client/src/tests -m "unit or contract"
3
4# 集成测试,需要可访问的 Server
5HUGEGRAPH_URL=http://127.0.0.1:8080 \
6HUGEGRAPH_GRAPH=hugegraph \
7HUGEGRAPH_USER=admin \
8HUGEGRAPH_PASSWORD=admin \
9uv run pytest hugegraph-python-client/src/tests -m "integration and hugegraph"

CI 的集成测试作业使用 hugegraph/hugegraph:1.7.0 镜像。需要非默认空间时,还可以设置 HUGEGRAPH_GRAPHSPACE。

源码与测试位于 hugegraph-python-client/src/pyhugegraph/ 和 hugegraph-python-client/src/tests/,可直接运行的示例在 hugegraph-python-client/src/pyhugegraph/example/hugegraph_example.py。

5.3 - HugeGraph Go 客户端快速入门

HugeGraph Go Client 是 Toolchain 仓库中的 Go SDK,目前提供版本查询、Schema(PropertyKey、VertexLabel、EdgeLabel)、顶点和 Gremlin API。边数据 API 尚未实现。

该模块仍在开发中。接口范围以 hugegraph-client-go/api/v1 下的源码为准。

环境要求

  • Go 1.19 或更高版本
  • 可访问的 HugeGraph Server,默认示例地址为 http://127.0.0.1:8080

安装

在 Go module 项目中执行:

1go get github.com/apache/hugegraph-toolchain/hugegraph-client-go

初始化客户端

NewCommonClient 要求 Host 是 IP 地址,Port 在 1 到 65535 之间;客户端始终使用明文 HTTP 连接。未启用认证时,用户名和密码留空;只有两者都设置时才会发送 Basic Auth。

GraphSpace 非空时,Vertex 和 Schema API(Schema()、Propertykey、VertexLabel、EdgeLabel)使用 /graphspaces/{space}/graphs/{graph}/... 路径;留空时使用旧版 /graphs/{graph}/... 路径。默认图空间填写 DEFAULT。 Gremlin 默认 aliases 也使用 GraphSpace,空值按 DEFAULT 处理。Version() 始终请求 /versions,不依赖图空间。

 1package main
 2
 3import (
 4	"fmt"
 5	"log"
 6
 7	hugegraph "github.com/apache/hugegraph-toolchain/hugegraph-client-go"
 8)
 9
10func main() {
11	client, err := hugegraph.NewCommonClient(hugegraph.Config{
12		Host:       "127.0.0.1",
13		Port:       8080,
14		GraphSpace: "DEFAULT",
15		Graph:      "hugegraph",
16		Username:   "",
17		Password:   "",
18	})
19	if err != nil {
20		log.Fatal(err)
21	}
22
23	response, err := client.Version()
24	if err != nil {
25		log.Fatal(err)
26	}
27	defer response.Body.Close()
28
29	fmt.Println(response.Versions.Version)
30}

Version() 返回的 Versions 包含 HugeGraph Server、Core、Gremlin 和 REST API 版本。若使用源码提供的 NewDefaultCommonClient(),默认连接 127.0.0.1:8080 下的 hugegraph 图,使用 admin/pa 认证,并挂载一个打印全部请求和响应体的 ColorLogger;生产代码通常应显式传入配置。

配置项

hugegraph.Config 包含以下字段:

字段类型说明
HoststringHugeGraph Server 的 IP 地址,不支持主机名
PortintHugeGraph Server 的 REST 端口,取值 1 到 65535
GraphSpacestringVertex、Schema API 和 Gremlin 默认 aliases 使用的图空间;默认空间填写 DEFAULT
GraphstringServer 上配置的图名
UsernamestringServer 用户名,未启用认证时填空字符串
PasswordstringServer 密码,未启用认证时填空字符串
Transporthttp.RoundTripper自定义 HTTP transport,为 nil 时使用 http.DefaultTransport
Loggerhgtransport.Logger请求/响应日志,为 nil 时不记录日志

hgtransport 包提供四种 logger:TextLogger(纯文本)、ColorLogger(终端彩色)、CurlLogger(可执行的 curl 命令)和 JSONLogger(JSON 行)。它们的字段相同:Output(io.Writer)、EnableRequestBody 和 EnableResponseBody。

 1import (
 2	"os"
 3
 4	hugegraph "github.com/apache/hugegraph-toolchain/hugegraph-client-go"
 5	"github.com/apache/hugegraph-toolchain/hugegraph-client-go/hgtransport"
 6)
 7
 8client, err := hugegraph.NewCommonClient(hugegraph.Config{
 9	Host:  "127.0.0.1",
10	Port:  8080,
11	Graph: "hugegraph",
12	Logger: &hgtransport.ColorLogger{
13		Output:             os.Stdout,
14		EnableRequestBody:  true,
15		EnableResponseBody: true,
16	},
17})

已实现的入口

CommonClient 当前公开以下入口:

入口用途
Version()查询服务端版本
Schema()查询完整 Schema
PropertykeyCreate、GetAll、GetByName、UpdateUserdata、DeleteByName
VertexLabelCreate、GetAll、GetByName、UpdateUserdata、DeleteByName
EdgeLabelCreate、GetAll、DeleteByName
VertexCreate、BatchCreate、UpdateProperties(通过 WithAction 指定 append 或 eliminate)
GremlinGet 和 Post。Post 默认 language 为 gremlin-groovy,根据 GraphSpace 和 Graph 自动填充 graph/g aliases,并在 Data 中返回解析后的结果;Get 只返回状态码,并把原始响应打印到 stdout。

每个操作都通过挂在操作本身上的 With... 函数式选项传参,例如 client.Gremlin.Post.WithGremlin(...) 或 client.Propertykey.GetByName.WithName(...)。

EdgeLabel.Create 的请求数据允许 Properties: nil 或空切片 []string{},用于创建无属性的边标签。

类型化 API 返回的 err 表示参数校验、传输、响应读取或 JSON 解码错误。 HTTP 4xx/5xx 仍可能返回 err == nil,例如创建顶点时指定不存在的 label 会返回 HTTP 400。 读取结果数据前,请检查 response.StatusCode 是否属于 2xx。调用 Gremlin.Post 时,还需检查 response.Data.Status.Code 是否为成功的 Gremlin 协议状态码(2xx)。

 1resp, err := client.Gremlin.Post(
 2	client.Gremlin.Post.WithGremlin("g.V().limit(3)"),
 3)
 4if err != nil {
 5	log.Fatal(err)
 6}
 7defer resp.Body.Close()
 8if resp.StatusCode < 200 || resp.StatusCode >= 300 {
 9	log.Fatalf("HugeGraph returned HTTP %d", resp.StatusCode)
10}
11if resp.Data.Status.Code < 200 || resp.Data.Status.Code >= 300 {
12	log.Fatalf("Gremlin returned status %d: %s", resp.Data.Status.Code, resp.Data.Status.Message)
13}
14fmt.Println(resp.Data.Result.Data)

Vertex 相关操作的入参是 internal/model 包中的 model.Vertex[any]。Go 不允许从其他 module 导入 internal 包,因此目前 Vertex API 只能在客户端 module 内部调用;其测试文件也已全部注释。

完整调用方式可参考各 API 目录中的测试,例如 version_test.go、gemlin_test.go 和 vertexlabel_test.go。