使用 ttrpc 实现高效的进程间通信(附 Go Demo)
ttrpc
(Tiny Transport RPC)是由 containerd 社区开发的一种轻量级 RPC 协议,它专为本地进程间通信(IPC)设计,使用 UNIX domain socket 与 protobuf,实现了比 gRPC 更快、更小、更适合容器运行时的通信机制。
本文将介绍:
- ttrpc 是什么
- ttrpc 与 gRPC 的区别
- 如何使用 ttrpc 开发一个服务端和客户端
- 完整 Demo 与运行方法
✳️ 一、ttrpc 简介
ttrpc
是一个基于 Protobuf 的简化 RPC 框架,主要用于容器运行时如 containerd
与其 shim
之间的通信。相比 gRPC,它去除了 TLS、多路复用、流式接口等复杂功能,专注于在同主机中通过 UNIX socket 进行高性能通信。
✅ 特点
特性 | ttrpc | gRPC |
---|---|---|
通信协议 | Protobuf over UNIX socket | Protobuf over HTTP/2 |
TLS 支持 | ❌ 不支持 | ✅ 支持 |
多路复用 | ❌ 不支持 | ✅ 支持 |
使用场景 | 本地进程通信(如 shim) | 网络服务间通信 |
性能开销 | ✅ 极小 | ❌ 相对较大 |
🔧 二、环境准备
1. 安装依赖
确保 Go 和 protoc 安装完成:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install github.com/containerd/ttrpc/cmd/protoc-gen-go-ttrpc@latest
将 $GOPATH/bin
加入 PATH:
export PATH=$PATH:$HOME/go/bin
📁 三、定义 Protobuf 接口(hello.proto)
创建文件 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 框架,特别适合容器运行时、shim 等无需网络的通信场景:
- 更快:无 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 路径一致且权限正确 |