Kitex是字节跳动开源的go语言rpc框架,相较于其他rpc框架kitex使用了新的网络包,实现了多路复用的连接及其管理并使用自建内存池,提高效率,并且支持idl解析和代码生成,同时不仅支持thrift协议,也支持基于protobuf的grpc通讯,本文主要介绍使用kitex搭建一个由A->B的grpc通讯
下载Kitex
使用命令go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
下载最新版的kitex
下载成功后使用kitex --version
查看kitex版本如果安装成功会出现如下
$ kitex --version
vx.x.x
定义idl文件
使用kitex框架定义的idl文件要基于proto3,语法可以参考https://developers.google.com/protocol-buffers/docs/gotutorial
定义一下两个proto文件:
注意定义的idl文件都需要定义go_package
base.proto
syntax="proto3";
package base;
option go_package = "base";
message Base {
string LogID =1;
string Caller =2;
string Addr = 3;
string Client = 4;
map<string, string> Extra=6;
}
message BaseResp {
string StatusMessage = 1;
int32 StatusCode = 2;
map<string, string> Extra=3;
}
rpc服务文件:myservice.proto
syntax="proto3";
package pbdemo;
option go_package = "pbdemo";
import "base.proto";
enum TestEnum {
ZERO = 0;
FIRST = 1;
SECOND = 2;
THIRD = 3;
FOURTH = 4;
}
message MyRequest {
string msg = 1;
base.Base Base = 255;
}
message MyResponse {
string msg = 1;
base.BaseResp BaseResp = 255;
}
service MyService {
rpc TestMethod1(MyRequest) returns (MyResponse);
}
定义好了idl文件,我们就可以使用kitex生成grpc的client和service代码
客户端代码生成
使用kitex生成客户端代码使用以下命令行代码
kitex -module $your_module_name -type protobuf -I $your_idl_package/ $your_idl_package/$your_idl_name.proto
- -module 后添加go mod对应的模块名称
- -I 用于添加 IDL 的搜索目录(for includes)
生成后的代码位于kitex_gen文件夹中
服务端代码生成
使用kitex生成服务端代码使用以下命令行代码
kitex service $your_service_name -module $your_module_name -type protobuf -I $your_idl_package/ $your_idl_package/$your_idl_name.proto
- -module参数表明生成代码的go mod中的module name
- -service参数表明需要生成服务端代码,同时需要指定服务端的PSM
生成后的代码位于kitex_gen文件夹中
编写服务端代码
使用kitex生成代码后,会生成对应的handler文件,在handler文件中完成业务逻辑
如本例子中的handler在完成业务逻辑后如下
package main
import (
"context"
"fmt"
pbdemo "rpcServerDemo/kitex_gen/pbdemo"
)
// MyServiceImpl implements the last service interface defined in the IDL.
type MyServiceImpl struct{}
// TestMethod1 implements the MyServiceImpl interface.
func (s *MyServiceImpl) TestMethod1(ctx context.Context, req *pbdemo.MyRequest) (resp *pbdemo.MyResponse, err error) {
// TODO: Your code here...
fmt.Println("Received:", req.Msg)
resp = &pbdemo.MyResponse{
Msg: "I am happy to receive your message!",
}
return resp, nil
}
实现了简单的rpc通讯,在收到对方的request之后会发送给对发一个简单的response
编写客户端代码
客户端主要通过main远程调用服务端的rpc service,实现逻辑如下
package main
import (
"code.byted.org/kite/kitex/client"
"code.byted.org/kite/kitex/transport"
"context"
"fmt"
"rpcDemo/api/kitex_gen/pbdemo"
"rpcDemo/api/kitex_gen/pbdemo/myservice"
)
func main() {
var opts []client.Option
// specify the address of the server
opts = append(opts, client.WithHostPorts("localhost:8888"))
opts = append(opts, client.WithTransportProtocol(transport.GRPC))
// construct a client
cli := myservice.MustNewClient("kitex.grpc.example", opts...)
ctx := context.Background()
// initialize one request
req := &pbdemo.MyRequest{
Msg: "Hello",
}
// make a call
resp, err := cli.TestMethod1(ctx, req)
if err != nil {
fmt.Printf("failed: %s\n", err.Error())
} else {
fmt.Printf("OK: %s\n", resp.Msg)
}
}
首先我们通过options来定义对方的ip地址,同时使用grpc时需要指明rpc传输类型,之后通过kitex创建新的客户端,定义服务端的psm
服务端启动
首先获取相关依赖:
$ go get -u
所有依赖安装完成后,我们就可以编译运行我们的服务端代码。
通过执行build.sh来完成服务端的构建。
sh build.sh
编译成功后,看一下目录中,新增了一个output目录:
output
├── bin // 真正可执行文件所在的目录
│ └── kitex.thrift.example
├── bootstrap.sh // 运行的脚本
├── conf // 配置文件所在目录,每一次编译都会将 conf 目录下的文件复制到这里
│ └── kitex.yml
└── settings.py // 无视它就好
最后通过运行 sh output/bootstrap.sh,就可以看到运行的输出:
$ sh output/bootstrap.sh
[Metrics(v3)] metrics new writer error: [metrics sdk can not get agent socket path], all metrics would be dropped
[Metrics(v3)] metrics new writer error: [metrics sdk can not get agent socket path], all metrics would be dropped
Info 2021-10-11 16:50:37,789 v1(7) client.go:58 172.17.196.252 kitex.thrift.example - default - 0 not prod environment, skip collect version info
[Metrics(v3)] metrics new writer error: [metrics sdk can not get agent socket path], all metrics would be dropped
客户端启动
运行main函数
可以看到
OK: I am happy to receive your message!
说明客户端和服务端完成通信
这样我们的简易grpc通信就搭建好了