引言

如果你已经完成了 快速上手教程,那么下一步就是要理解 OpenClaw 的架构设计。本文会带你逐层拆解 OpenClaw 的核心模块,让你不仅会用,还能理解它为什么这样设计。

整体架构概览

OpenClaw 的代码组织遵循"高内聚、低耦合"的模块化原则,主要分为四大子系统:

┌──────────────────────────────────────────────┐
│              Application Layer               │
│   (CLI / Web Server / Scheduler / Worker)    │
└──────────────────┬───────────────────────────┘
                   │
┌──────────────────▼───────────────────────────┐
│           Plugin Manager (插件总线)           │
└──┬───────────┬─────────────┬─────────────────┘
   │           │             │
┌──▼────┐  ┌───▼─────┐  ┌────▼─────────┐
│Runtime│  │ Engine  │  │AssetPipeline │
│  运行时 │ │ 核心引擎 │  │ 资源管道      │
└───────┘  └─────────┘  └──────────────┘
                   │
         ┌─────────▼─────────┐
         │  NetworkSync      │
         │  网络同步层         │
         └───────────────────┘

下面我们逐一深入。

一、Runtime 模块(运行时)

Runtime 是 OpenClaw 的"心脏",负责整个程序的生命周期管理。它的设计哲学是:

把"启动顺序、依赖装配、优雅停机"这些脏活,全部下沉到 Runtime,业务代码只关心"做什么"。

核心接口

// pkg/runtime/runtime.go
type Runtime interface {
    // 注册组件
    Register(name string, component Component) error
    // 启动 Runtime,会按依赖顺序调用各 Component.Start
    Start(ctx context.Context) error
    // 优雅停机
    Shutdown(ctx context.Context) error
    // 获取已注册的组件
    Get(name string) (Component, bool)
}

启动流程

Init → LoadConfig → RegisterComponents → ResolveDeps → Start (并发) → Ready → 接收信号 → Shutdown

OpenClaw Runtime 通过 依赖图 决定启动顺序,避免硬编码。每个 Component 实现:

type Component interface {
    Name() string
    DependsOn() []string           // 依赖的其他组件名
    Start(ctx context.Context) error
    Shutdown(ctx context.Context) error
}

例如 WebServer 依赖 ConfigCenterLogger,那么 Runtime 会保证这两个组件先启动。

二、Engine 模块(核心引擎)

Engine 是真正干活的"引擎"。OpenClaw 内置了 4 种 Engine:

Engine职责典型应用
TaskEngine调度异步任务后台批处理、定时任务
StreamEngine处理流式数据实时日志、消息推送
EventEngine事件驱动监听 Kafka / Redis 事件
RuleEngine规则匹配业务规则、风控

一个简单的 TaskEngine 示例

eng := engine.NewTaskEngine()
eng.Submit(&engine.Task{
    Name: "send-email",
    Fn: func(ctx context.Context) error {
        return mailer.Send(ctx, "user@example.com", "Hello!")
    },
    Retry: 3,
    Timeout: 30 * time.Second,
})
eng.Run(ctx)

Engine 内部使用 工作池(worker pool)+ 任务队列,默认根据 CPU 核数自动调整并发度。

三、AssetPipeline 模块(资源管道)

资源管道用于处理"输入 → 转换 → 输出"的流水线场景。比如:

  • 视频文件:上传 → 转码(H.264)→ 打水印 → 推送到 CDN
  • 数据文件:CSV → 清洗 → 写入数据库 → 生成报告
pipeline := asset.NewPipeline("video-transcode")
pipeline.AddStage("download", downloadStage)
pipeline.AddStage("transcode", transcodeStage, asset.WithConcurrency(4))
pipeline.AddStage("upload", uploadStage)

pipeline.On("stage-finished", func(e *asset.Event) {
    log.Printf("Stage %s finished in %v", e.Stage, e.Duration)
})

pipeline.Run(ctx, input)

💡 AssetPipeline 的核心优势是 可观测性:每个 stage 都暴露耗时、成功率、错误日志,方便排查瓶颈。

四、NetworkSync 模块(网络同步层)

当 OpenClaw 部署为集群时,NetworkSync 负责节点间的状态同步:

  • 配置变更广播
  • Leader 选举
  • 分布式锁
  • 节点健康心跳

底层支持 etcd / Consul / Redis 三种后端,可通过配置切换:

# config.yaml
network_sync:
  backend: etcd
  endpoints:
    - http://etcd-1:2379
    - http://etcd-2:2379
    - http://etcd-3:2379
  lease_ttl: 30s

五大设计原则

阅读源码时,你会发现 OpenClaw 始终贯彻以下原则:

  1. 接口优先:所有模块都通过 interface 暴露能力,便于替换实现。
  2. 依赖注入:避免硬编码依赖,方便单元测试。
  3. 可观测性:内置 metrics、tracing、logging 三件套。
  4. 可扩展性:所有 Engine、Pipeline 都允许自定义 Stage。
  5. 优雅停机:收到 SIGTERM 后会等待正在执行的任务完成,再释放资源。

总结

理解 OpenClaw 架构后,你会发现它本质上是一个 "可拼装的分布式应用骨架"。Runtime 负责组装,Engine 负责执行,Pipeline 负责数据流转,NetworkSync 负责集群协调。

下一篇我们会基于这套架构,做一个完整 插件开发实战

延伸阅读