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

发布于:2025-06-25 ⋅ 阅读:(21) ⋅ 点赞:(0)

使用 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 路径一致且权限正确

网站公告

今日签到

点亮在社区的每一天
去签到