Skip to content

Go SDK 架构解析

Go SDK 是 CubeSandbox 的官方客户端库,提供沙箱创建、代码执行、文件操作等能力。这篇文章拆解它的对象模型、请求通道和 Connect 协议实现。


1. SDK 对象模型


2. 双 HTTP Client 设计

SDK 有两个独立的 HTTP client,分别走不同的通道:

controlHTTP

走标准 HTTP 代理,用于控制面请求:

  • POST /sandboxes — 创建沙箱
  • DELETE /sandboxes/:id — 销毁沙箱
  • POST /sandboxes/:id/pause — 暂停
  • GET /sandboxes/:id — 查询信息

dataHTTP

绕过代理,直连 CubeProxy,用于数据面请求:

  • POST /process.Process/Start — 执行代码
  • GET /files — 读取文件
  • POST /files — 写入文件
go
// transport.go
func newDataHTTPClient(cfg Config) *http.Client {
    transport := http.DefaultTransport.(*http.Transport).Clone()
    transport.Proxy = nil  // 绕过代理

    if cfg.ProxyNodeIP != "" {
        target := net.JoinHostPort(cfg.ProxyNodeIP, strconv.Itoa(cfg.ProxyPortHTTP))
        transport.DialContext = func(ctx context.Context, network, _ string) (net.Conn, error) {
            return dialer.DialContext(ctx, network, target)
        }
    }
    return &http.Client{Transport: transport}
}

3. Sandbox 生命周期

GetHost 的域名格式

go
func (s *Sandbox) GetHost(port int) string {
    return fmt.Sprintf("%d-%s.%s", port, s.SandboxID, s.Domain)
    // 例如: 49999-abc123.cube.app
}

这个域名会被 DNS 解析到运行该沙箱的节点 IP,CubeProxy 根据 Host header 路由到正确的沙箱。


4. Commands.Run:命令执行

go
// commands.go
func (c *Commands) Run(ctx context.Context, cmd string, opts CommandOptions) (*CommandResult, error) {
    process, err := c.starter.startProcess(ctx, processStartRequest{
        Process: processConfig{
            Cmd:  "/bin/bash",
            Args: []string{"-l", "-c", cmd},
            Envs: envs,
            Cwd:  opts.Cwd,
        },
        Stdin: &stdin,
    }, opts)
    return &CommandResult{
        Stdout:   process.Stdout,
        Stderr:   process.Stderr,
        ExitCode: process.ExitCode,
    }, nil
}

所有命令都通过 /bin/bash -l -c 包装,确保:

  • 使用 login shell 加载环境变量
  • 支持管道、重定向等 shell 特性

5. Connect 协议:流式命令执行

envd.go 中的 startProcess 使用 Connect 协议与 envd 通信:

Envelope 格式

[1 byte flags][4 bytes length][payload JSON]
  • flags & 0x01:压缩标志
  • flags & 0x02:end stream 标志

事件类型

事件字段说明
startpid进程启动
datastdout, stderr, pty输出数据
endexitCode, status进程结束
keepalive-心跳保活

6. 文件操作

文件操作通过 envd 的 HTTP API 实现:

go
// envd.go
func (s *Sandbox) readFile(ctx context.Context, path string) (string, error) {
    query := url.Values{"path": []string{path}}
    req, _ := s.newEnvdRequest(ctx, http.MethodGet, "/files", query, nil)
    resp, _ := s.client.dataHTTP.Do(req)
    raw, _ := io.ReadAll(resp.Body)
    return string(raw), nil
}

请求目标:http://{port}-{sandboxID}.{domain}/files?path=/path/to/file


7. 配置加载

go
// config.go
type Config struct {
    ApiURL        string  // CubeAPI 地址
    ApiKey        string  // API Key
    SandboxDomain string  // 沙箱域名
    Timeout       time.Duration
    ProxyNodeIP   string  // 直连节点 IP
    ProxyPortHTTP int     // CubeProxy HTTP 端口
    ProxyScheme   string  // http / https
}

配置优先级:环境变量 → 显式传入 → 默认值

环境变量说明
CUBESANDBOX_API_URLCubeAPI 地址
CUBESANDBOX_API_KEYAPI Key
CUBESANDBOX_DOMAIN沙箱域名
CUBESANDBOX_TIMEOUT超时时间

延伸阅读