[ Golang RPC框架之Kitex | 青训营笔记]

192 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天

Kitex介绍

  1. Kitex是字节跳动内部的Golang微服务RPC框架,具有高性能,强拓展性的特点
  2. 使用自研的高性能网络库 Netpoll,性能相较 go net 具有显著优势
  3. 支持多类RPC消息协议:ThriftKitex ProtobufgRPC。除此之外,使用者也可以扩展自己的消息协议(注:thrift 既是 IDL 格式,同时也是序列化协议和传输协议)
  4. Kitex 支持的传输协议有 TTHeaderHTTP2
  5. Kitex支持的消息协议有PingPongOneway双向 Streaming
  6. 支持服务注册/发现、负载均衡、熔断、限流、重试、监控、链路跟踪、日志、诊断等服务治理模块
  7. 内置同名代码生成工具 kitex,支持更加IDL文件生成 ThriftProtobuf 以及脚手架代码
  8. 性能测试较 grpc, rpcx要更优秀

Kitex实践

安装代码生成工具

  1. 安装Kitex的代码生成工具 kitex

    # 安装
    go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
    # 验证
    kitex --version
    
  2. 要使用 thrift 或 protobuf 的 IDL 生成代码,需要安装相应的编译器:thriftgoprotoc

    # thriftgo
    go install github.com/cloudwego/thriftgo@latest
    # 验证
    thriftgo --version
    
    • kitex 生成的代码里,一部分是kitex 会调用 thriftgo 等编译器生成的,另一部分是用于连接 Kitex 框架与生成代码并提供给终端用户良好界面的胶水代码
    • kitex 生成的代码会依赖相应的 Go 语言代码库
      1. 对于 thrift IDL,是 github.com/apache/thrift v0.13.0(v0.14.0 版本开始提供的 API 和之前的版本是不兼容的)
      2. 对于 protobuf IDL,是 google.golang.org/protobuf v1.26.0

IDL文件编写

使用thrift编写IDL文件

namespace go api

struct Request {
        1: string message
}

struct Response {
        1: string message
}

struct AddRequest {
  1: i64 first
  2: i64 second
}

struct AddResponse {
  1: i64 sum
}

service Hello {
    Response echo(1: Request req)
    AddResponse add(1: AddRequest req)
}

生成代码

# 语法
kitex [options] IDLAddress

# 若当前目录不在 $GOPATH/src 下,需要加上 -module 参数,一般为 go.mod 下的名字
kitex -module "your_module_name" -service service_name hello.thrift

#---------------------------示例-----------------------------------------
# 生成客户端代码
kitex hello.thrift
# 生成服务端代码
kitex -service hello hello.thrift

代码结构

.
├── build.sh                      // 服务的构建脚本,会创建一个名为 output 的目录并生成启动服务所需的文件到里面
├── handler.go                    // 用户在该文件里实现 IDL service 定义的方法
├── kitex_gen                     // IDL 内容相关的生成代码
│   ├── hello                     // hello.thrift 的生成代码
│       ├── hello.go              // thriftgo 的产物,包含 hello.thrift 定义的内容的 go 代码
│       ├── k-hello.go            // kitex 在 thriftgo 的产物之外生成的代码
│       └── helloservice          // kitex 为 hello.thrift 里定义的 hello.thrift 生成的代码
│           ├── helloservice.go   // 提供了 client.go 和 server.go 共用的一些定义
│           ├── client.go         // 提供了 NewClient API
│           └── server.go         // 提供了 NewServer API
├── main.go                       // 程序入口
└── script                        // 构建脚本
    └── bootstrap.sh              // 服务的启动脚本,会被 build.sh 拷贝至 output 下

如果不指定 -service 参数,那么生成的只有 kitex_gen 目录,可以用 kitex -hkitex --help 来查看 kitex 的所有可用的选项。

编写服务端业务逻辑

上述步骤完成后,./handler.go 中会自动生成Echo和Add方法,例如

// Add implements the HelloImpl interface.
func (s *HelloImpl) Add(ctx context.Context, req *api.AddRequest) (resp *api.AddResponse, err error) {
        // TODO: Your code here...
        return
}

// Echo implements the HelloImpl interface.
func (s *HelloImpl) Echo(ctx context.Context, req *api.EchoRequest) (resp *api.EchoResponse, err error) {
        // TODO: Your code here...
        return
}

编写客户端调用

服务端代码写好之后,即可在本服务或者其他服务上编写客户端代码,例如在./client/main.go 中编写调用服务端Echo方法:

req := &api.Request{Message: "my request"}
resp, err := client.Echo(context.Background(), req)
if err != nil {
    log.Fatal(err)
}
log.Println(resp)
time.Sleep(time.Second)

运行启动

  1. 服务端

    # cd到服务端main.go所在目录
    go run .
    
  2. 客户端

    # 另起一个终端,cd到客户端main.go所在目录
    go run .
    

参考资料

概览 | CloudWeGo

‌⁡⁤⁢⁣⁡⁢⁢⁣⁡⁡‍⁣⁢⁣⁣‬‬‌⁢⁤⁢⁣⁣⁣‌‬‬‍⁡‌‍‍‬Go 框架三件套详解.pptx - 飞书云文档 (feishu.cn)