Kitex 概述
Kitex 字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选择。
框架特点:
- 高性能:使用自研的高性能网络库 Netpoll,性能相较 go net 具有显著优势。
- 扩展性:提供了较多的扩展接口以及默认扩展实现,使用者也可以根据需要自行定制扩展。
- 多消息协议:RPC 消息协议默认支持 Thrift、Kitex Protobuf、gRPC。Thrift 支持 Buffered 和 Framed 二进制协议;Kitex Protobuf 是 Kitex 自定义的 Protobuf 消息协议,协议格式类似 Thrift;gRPC 是对 gRPC 消息协议的支持,可以与 gRPC 互通。除此之外,使用者也可以扩展自己的消息协议。
- 多传输协议:传输协议封装消息协议进行 RPC 互通,传输协议可以额外透传元信息,用于服务治理,Kitex 支持的传输协议有 TTHeader、HTTP2。TTHeader 可以和 Thrift、Kitex Protobuf 结合使用;HTTP2 目前主要是结合 gRPC 协议使用,后续也会支持 Thrift。
- 多种消息类型:支持 PingPong、Oneway、双向 Streaming。其中 Oneway 目前只对 Thrift 协议支持,双向 Streaming 只对 gRPC 支持
- 服务治理:支持服务注册/发现、负载均衡、熔断、限流、重试、监控、链路跟踪、日志、诊断等服务治理模块,大部分均已提供默认扩展,使用者可选择集成。
- 代码生成:Kitex 内置代码生成工具,可支持生成 Thrift、Protobuf 以及脚手架代码。
Kitex 快速开始
基于 IDL 的 KiteX 实践 在 RPC 框架中,我们知道,服务端与客户端通信的前提是远程通信,但这种通信又存在一种关联,那就是通过一套相关的协议(消息、通信、传输等)来规范,但客户端又不用关心底层的技术实现,只要定义好了这种通信方式即可。在 KiteX 中,也提供了一种生成代码的命令行工具:kitex,目前支持 thrift、protobuf 等 IDL,并且支持生成一个服务端项目的骨架。
- 创建并进入项目目录:
PS F:\work\Go\golangStudy> mkdir example
目录: F:\work\Go\golangStudy
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2023/8/27 15:09 example
PS F:\work\Go\golangStudy> cd example
- 安装 kitex:
PS F:\work\Go\golangStudy> go install github.com/cloudwego/kitex/tool/cmd/kitex\@latest
PS F:\work\Go\golangStudy\example> kitex
No IDL file found.
- 编写IDL
创建一个名为echo.proto的 protobuf IDL文件,然后在里面定义我们的服务
syntax = "proto3";
option go_package = "echo";
package echo;
message Request {
string message = 1;
}
message Response {
string message = 1;
}
service Echo {
rpc echo (Request) returns (Response);
rpc sayHello (Request) returns (Response);
}
- 生成 echo 服务代码
有了 IDL 以后我们便可以通过 kitex 工具生成项目代码了,执行如下命令:
PS F:\work\Go\golangStudy> kitex -module example -service example echo.proto
go: creating new go.mod: module example
上述命令中,-module 表示生成的该项目的 go module 名,-service 表明我们要生成一个服务端项目,后面紧跟的 example 为该服务的名字。最后一个参数则为该服务的 IDL 文件。
- 编写 echo 服务逻辑
package main
import (
"context"
echo "example/kitex_gen/echo"
)
// EchoImpl implements the last service interface defined in the IDL.
type EchoImpl struct{}
// Echo implements the EchoImpl interface.
func (s *EchoImpl) Echo(ctx context.Context, req *echo.Request) (resp *echo.Response, err error) {
// TODO: Your code here...
return &echo.Response{
Message: req.GetMessage(),
}, nil
}
// SayHello implements the EchoImpl interface.
func (s *EchoImpl) SayHello(ctx context.Context, req *echo.Request) (resp *echo.Response, err error) {
// TODO: Your code here...
return &echo.Response{
Message: "hello?",
}, nil
}
- 编写 main.go 文件
package main
import (
"context"
"example/kitex_gen/echo"
echo1 "example/kitex_gen/echo/echo"
"fmt"
"log"
"github.com/cloudwego/kitex/client"
)
func main() {
go func() {
svr := echo1.NewServer(new(EchoImpl))
err := svr.Run()
if err != nil {
log.Println(err.Error())
}
}()
go func() {
cli, err := echo1.NewClient("example", client.WithHostPorts("127.0.0.1:8888"))
if err != nil {
log.Fatal(err)
}
req := &echo.Request{Message: "我的第一个go请求"}
rsp, err := cli.Echo(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Println(rsp)
}()
select {}
}
- 编译运行
PS F:\work\Go\golangStudy> go build
PS F:\work\Go\golangStudy> ./example
2023/08/27 16:43:56.987455 server.go:83: [Info] KITEX: server listen at addr=[::]:8888
2023/08/27 16:43:57.045478 middlewares.go:130: [Warn] KITEX: auto retry retryable error, retry=1 error=remote or network error: get
connection error: dial tcp 127.0.0.1:8888: i/o timeout
2023/08/27 16:43:57 接收到client请求:我的第一个go请求
message:"我的第一个go请求"