dgraph 启动分析

10 阅读6分钟

dgraph 启动

  1. 子命令注册: 在 root.go 文件中,alpha 子命令通过 subcommands 切片注册到 RootCmd:
    var subcommands = []*x.SubCommand{ &alpha.Alpha, // 这里注册了 alpha 子命令 // 其他子命令... }
  2. 初始化子命令: 在 initCmds() 函数中,alpha 子命令被添加到 RootCmd:
    for _, sc := range subcommands { RootCmd.AddCommand(sc.Cmd) // 将 alpha 子命令注册到 RootCmd }
  3. 启动逻辑: alpha 子命令的具体实现位于 github.com/hypermodeinc/dgraph/v25/dgraph/cmd/alpha 包中。你需要查看 alpha 包中的代码,找到 Run 或 RunE 方法,这些方法定义了 Alpha Node 的启动逻辑。
  4. 执行命令: 在 Execute() 函数中,RootCmd.Execute() 被调用,解析命令行参数并执行对应的子命令:
    x.CheckfNoLog(RootCmd.Execute())
main.go
  |
  v
cmd.Execute()
  |
  v
Cobra: RootCmd.Execute()
  |
  v
Cobra: ExecuteC()
  |
  v
[解析命令行参数]
  |
  v
找到 alpha 子命令
  |
  v
执行 Alpha.Cmd.Run
  |
  v
调用 run() 函数

总结: 要自动启动 Alpha Node,可以直接运行以下命令:

dgraph alpha

启动参数

dgraph 全局启动参数

  • --cwd:指定工作目录(Change working directory to the path specified. The parent must exist.)
  • --profile_mode:启用性能分析模式,可选值有 cpu、mem、mutex、block
  • --block_rate:block profiling 采样率,需配合 block profile_mode 使用
  • --config:配置文件路径(Configuration file. Takes precedence over default values, but is overridden to values set with environment variables and flags.)
  • --bindall:是否监听所有本地地址(Use 0.0.0.0 instead of localhost to bind to all addresses on local machine.)
  • --expose_trace:允许 trace 端点被远程访问

此外,还会自动添加 Go 标准库 flag 包(如 glog 日志相关参数),包括但不限于:

  • --log_dir
  • --logtostderr
  • --alsologtostderr
  • --v
  • --stderrthreshold(始终被强制设为0,且标记为废弃)
  • --vmodule
  • --log_backtrace_at

alpha/zero common 启动参数

  • --my:指定本服务器的 addr:port,用于其他 Dgraph 服务器通信。
  • --trace:OpenCensus 跟踪相关参数,如采样比例、Jaeger 和 Datadog 的 URL。
  • --survive:数据持久化方式,process 表示进程崩溃无数据丢失,filesystem 表示每次写入后阻塞同步,保证硬重启无数据丢失。
  • --telemetry:遥测(诊断)相关参数,如是否发送匿名遥测数据、是否发送崩溃事件到 Sentry(已废弃)

Alpha Node 启动参数

dgraph alpha 的启动参数非常丰富,主要用于配置数据库的存储、网络、缓存、安全、GraphQL、审计、CDC、特性开关等。下面是主要参数的简要说明:

  • --postings:指定 posting list 的存储目录。
  • --wal:raft 日志的存储目录。
  • --tmp:临时文件目录。
  • --export:导出数据的目录。
  • --zero:Dgraph Zero 的地址(集群协调节点)。
  • --port_offset:端口偏移量,便于同机多实例部署。
  • --custom_tokenizers:自定义分词插件。
  • --mcp:是否同时启动 MCP server。
  • --badger:Badger 存储相关参数(如压缩、并发等)。
  • --cache:缓存相关参数(总大小、各类缓存百分比、写入时是否移除等)。
  • --raft:Raft 协议相关参数(节点ID、组ID、快照策略等)。
  • --security:安全相关参数(管理 token、白名单等)。
  • --limit:各种资源限制(如查询边数、节点数、mutation 模式、超时等)。
  • --graphql:GraphQL 服务相关参数(如 introspection、debug、lambda-url 等)。
  • --cdc:变更数据捕获(Change Data Capture)相关参数(如 kafka、认证、TLS 等)。
  • --audit:审计日志相关参数(输出位置、压缩、加密、保留天数、文件大小等)。
  • --feature-flags:实验性特性开关(如 normalize 兼容模式、详细指标等)。

Alpha 启动

run() 启动干了什么?

  1. 参数与配置初始化

    • 解析并校验所有配置(如缓存、Raft、安全、审计、GraphQL 等)。
    • 计算缓存分配比例,设置 Badger、缓存、Raft、白名单等参数。
  2. 安全与密钥处理

    • 加载 ACL、加密密钥,配置权限相关参数。
  3. Worker 配置与初始化

    • 构造 worker.Options,设置存储目录、缓存、审计、CDC 等。
    • 设置全局 x.WorkerConfig,并调用 worker.SetConfiguration
  4. 自定义分词器加载

    • 加载自定义分词器插件(如有配置)。
  5. 端口与限制参数设置

    • 设置端口偏移、各种查询/变更限制、GraphQL 相关参数。
  6. 打印版本与配置信息

    • 输出当前版本和配置信息到日志。
  7. Worker/Posting/Schema 初始化

    • 初始化底层存储、schema、posting list 索引等。
  8. 信号处理

    • 注册 OS 信号(如 Ctrl-C、SIGTERM)处理,优雅关闭服务。
  9. Raft 节点与 ACL 初始化

    • 启动 Raft 节点,初始化 ACL 账号与订阅。
  10. HTTP/GRPC 服务启动

    • 启动 HTTP 和 GRPC 服务,注册所有路由和处理器。
    • 支持 MCP(可选)。
  11. 健康检查与等待

    • 等待健康检查通过后,初始化审计日志。
  12. 主循环与关闭流程

    • 阻塞等待关闭信号,依次关闭各个子系统(如 worker、admin、audit、存储等)。

该流程涵盖了 Alpha 节点的所有初始化、配置、服务启动、信号处理和优雅关闭,是 Alpha 进程的主入口。

InitStorage()

InitStorageServerState 结构体的一个方法,用于初始化 Dgraph 服务端的存储相关资源。其主要功能如下:

  1. 加密功能检测
    检查是否启用了加密(x.WorkerConfig.EncryptionKey),如果启用则打印日志。

  2. 初始化 Write Ahead Log (WAL) 存储

    • 创建 WAL 目录(Config.WALDir)。
    • 使用加密密钥(如果有)初始化 WAL 存储(raftwal.InitEncrypted)。
  3. 初始化 Postings 存储

    • 创建 Postings 目录(Config.PostingDir)。
    • 配置 Badger 数据库选项,包括目录、版本数、命名空间偏移等。
    • 打印 Badger 配置信息(不暴露加密密钥)。
    • 打开 Badger 管理模式数据库(badger.OpenManaged)。
  4. 初始化临时目录
    创建临时目录(x.WorkerConfig.TmpDir)。

  5. 启动后台协程

    • 启动 Value Log GC 协程(x.RunVlogGC)。
    • 启动缓存健康监控协程(x.MonitorCacheHealth)。
    • 启动磁盘指标监控协程(x.MonitorDiskMetrics)。

该函数确保所有存储相关的目录和资源都已正确创建和初始化,并启动必要的后台任务以保证系统的健康运行。

InitTasks()
  1. 初始化任务日志存储
    通过 filepath.Join 拼接出任务日志文件路径,然后用 z.NewTreePersistent 打开或创建一个持久化的任务日志(通常是一个键值存储)。

  2. 初始化全局任务队列和相关资源
    创建一个带缓冲区的 channel(任务请求队列),互斥锁(用于并发保护),以及一个基于当前时间种子的随机数生成器。
    这些资源被封装到全局变量 Tasks 中。

  3. 恢复任务状态
    遍历任务日志中的所有任务,如果发现有任务处于“排队”或“运行中”状态,则将其标记为“失败”。
    这样可以保证系统重启后,未完成的任务不会被遗漏或卡住。

  4. 启动任务处理协程
    最后,启动一个 goroutine,异步处理任务队列中的任务。

简要总结:
InitTasks 负责初始化任务队列、任务日志和相关并发资源,并在服务启动时自动恢复未完成任务的状态,确保任务系统的健壮性和一致性。