初探kitex | 青训营笔记

154 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天,记录一下对 kitex 框架的学习。

什么是 kitex

Kitex[kaɪt’eks] 字节跳动内部的 Golang 微服务 RPC 框架,具有高性能强可扩展的特点,在字节内部已广泛使用。

快速开始

Kitex 默认支持 thrift、kitex protobuf 和 grpc,本文的实验中只使用了 kitex + thrift 的组合。

下载
  1. 安装 kitex:go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
  2. 安装 thriftgo:go install github.com/cloudwego/thriftgo@latest
  3. 执行kitex --versionthrift --version,测试是否安装成功。
 $ kitex --version
 v0.4.4
 ​
 $ thriftgo --version
 thriftgo 0.2.5
编写 thrift idl

在文件 hello.thrift 文件中编写 idl。

下面的 idl 定义了一个名为 hello 的 service,它包含一个接口 echo,入参是 Request,出参是Response。

 namespace go api
 ​
 struct Request {
         1: string message
 }
 ​
 struct Response {
         1: string message
 }
 ​
 service Hello {
     Response echo(1: Request req)
 }
生成代码

运行命令kitex -module hello -service HelloService hello.thrift即可生成代码。

-module 用来指定生成的 module 的名字,-service用来指定 service 的名字。

生成的目录结构如下。

 |-- build.sh                        构建工程的脚本
 |-- go.mod
 |-- handler.go                      idl定义的接口的空实现
 |-- hello.thrift                    我们编写的idl
 |-- kitex.yaml                      记录kitex版本和service名称
 |-- kitex_gen
 |   `-- api
 |       |-- hello
 |       |   |-- client.go           客户端相关方法
 |       |   |-- hello.go
 |       |   |-- invoker.go
 |       |   `-- server.go           服务端相关方法
 |       |-- hello.go
 |       |-- k-consts.go
 |       `-- k-hello.go
 |-- main.go                         服务端入口
 `-- script
     `-- bootstrap.sh

其中 handler.go 提供了 idl 定义的接口的空实现,需要我们补充对应的业务逻辑。

 ...
 // HelloImpl implements the last service interface defined in the IDL.
 type HelloImpl struct{}
 ​
 // Echo implements the HelloImpl interface.
 func (s *HelloImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
     // TODO: Your code here...
     return
 }
补充代码

让 Echo 方法简单的返回 Request 中的 Message。

 func (s *HelloImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
     return &api.Response{Message: req.Message}, nil
 }
运行服务端

运行命令go mod tidygo build hello,发现在 build 的时候报错了,错误与 thrift 相关。该问题在官方文档中也有描述。

出现 Thrift 接口编译问题,如 not enough arguments in call to iprot.ReadStructBegin

Kitex 依赖 Thrift v0.13,因为Apache Thrift v0.14 接口有 breaking change,无法直接升级。出现该问题是拉到了新版本的 Thrift,升级版本时建议不使用 -u 参数,可以执行命令固定版本 go mod edit -replace github.com/apache/thri…

解决问题后,重新运行上面的命令得到可执行文件 hello,运行命令./hello即可看到服务端可以正常运行了。

编写客户端

在与服务端工程同级目录下新建一个客户端工程。

 | -- hello_server   服务端
 | -- hello_client   客户端

要构建客户端,还需要之前 kitex 生成的代码,可以在 go.mod 中导入。

 require hello_server v0.0.0
 replace hello_server => ../hello_server

参考官方文档编写一个简单的客户端,代码如下。

 ...
 func main() {
     c, err := echo.NewClient("example", client.WithHostPorts("0.0.0.0:8888"))
     if err != nil {
         log.Fatal(err)
     }
     req := &api.Request{Message: "my request"}
     resp, err := c.Echo(context.Background(), req, callopt.WithRPCTimeout(3*time.Second))
     if err != nil {
     log.Fatal(err)
     }
     log.Println(resp)
 }
运行客户端

在服务端开启的情况下运行客户端,可以看到如下输出。

 2023/01/18 20:50:08 Response({Message:hello})
其他

上面的例子中服务端业务代码和 kitex 生成的代码耦合到了一起,客户端又依赖了服务端代码,耦合性太高,不利于维护。比较合适的结构应该是分为服务端、客户端和 rpc sdk(即 kitex 生成的代码)三个模块,服务端和客户端分别去依赖 rpc sdk。

参考

www.cloudwego.io/zh/docs/kit…