使用 ttrpc 实现高效的进程间通信(附 Go Demo)

共计 2491 个字符,预计需要花费 7 分钟才能阅读完成。

使用 ttrpc 实现高效的进程间通信(附 Go Demo)

本文介绍专为容器运行时设计的轻量级 RPC 框架 ttrpc,包含完整实现代码和运行示例。

什么是 ttrpc?

ttrpc(Tiny Transport RPC)是由 containerd 社区开发的一种轻量级 RPC 协议,专为本地进程间通信(IPC)设计。它使用 UNIX domain socket 与 protobuf,实现了比 gRPC 更快、更小、更适合容器运行时的通信机制。

ttrpc 与 gRPC 的核心区别

特性 ttrpc gRPC
通信协议 Protobuf over UNIX socket Protobuf over HTTP/2
TLS 支持 ❌ 不支持 ✅ 支持
多路复用 ❌ 不支持 ✅ 支持
主要场景 本地进程通信(如 shim) 网络服务间通信
性能开销 ✅ 极小 ❌ 相对较大

环境准备

安装必要依赖

# 安装 protoc
sudo apt install protobuf-compiler

# 安装 protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

# 安装 protoc-gen-go-ttrpc
go install github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@latest

# 将 GOPATH/bin 加入 PATH
export PATH=$PATH:$GOBIN

定义 Protobuf 接口

创建 hello.proto 文件:

syntax = "proto3";

package hello;

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

生成 ttrpc 代码

执行以下命令生成 Go 代码:

protoc \
  --go_out=. \
  --go-ttrpc_out=. \
  --go_opt=paths=source_relative \
  --go-ttrpc_opt=paths=source_relative \
  hello.proto

生成的文件:

  • hello.pb.go:Protobuf 消息定义
  • hello.ttrpc.pb.go:ttrpc 服务/客户端接口

服务端实现(模拟 shim)

创建 server.go

package main

import (
    "context"
    "fmt"
    "net"
    "os"

    "github.com/containerd/ttrpc"
    pb "yourmodule/hello" // 修改为实际模块路径
)

type helloService struct{}

func (s *helloService) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello, " + req.Name}, nil
}

func main() {
    socket := "/tmp/hello.sock"
    _ = os.Remove(socket)

    l, err := net.Listen("unix", socket)
    if err != nil {
        panic(err)
    }

    server := ttrpc.NewServer()
    pb.RegisterHelloService(server, &helloService{})

    fmt.Println("shim 服务启动,监听:", socket)
    if err := server.Serve(context.Background(), l); err != nil {
        panic(err)
    }
}

客户端实现(模拟 containerd)

创建 client.go

package main

import (
    "context"
    "fmt"
    "net"
    "time"

    "github.com/containerd/ttrpc"
    pb "yourmodule/hello" // 修改为实际模块路径
)

func main() {
    conn, err := net.Dial("unix", "/tmp/hello.sock")
    if err != nil {
        panic(err)
    }
    defer conn.Close()

    client := ttrpc.NewClient(conn)
    defer client.Close()

    c := pb.NewHelloServiceClient(client)

    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()

    resp, err := c.SayHello(ctx, &pb.HelloRequest{Name: "小诸葛"})
    if err != nil {
        panic(err)
    }

    fmt.Println("收到响应:", resp.Message)
}

运行 Demo

1. 启动服务端

go run server.go

输出:

shim 服务启动,监听: /tmp/hello.sock

2. 运行客户端(新终端)

go run client.go

输出:

收到响应: Hello, 小诸葛

总结

ttrpc 提供了一个专为本地通信优化的 RPC 框架,特别适合以下场景:

  • 更快:无 HTTP/TLS 负担
  • 更轻:简单 protobuf 实现
  • 更专注:适用于容器生命周期控制等场景

常见问题排查

问题 解决办法
protoc-gen-go-ttrpc not found 执行 go install github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@latest 并加入 PATH
import path 错误 确保 import "yourmodule/hello" 指向实际的模块路径
socket 无法连接 确保服务端正在运行,socket 路径一致且权限正确

ttrpc 作为容器生态中的重要组件,为进程间通信提供了高性能的解决方案,特别适合需要低延迟、高吞吐的本地服务调用场景。

正文完
 0
评论(没有评论)