文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
介绍同样是字节跳动开源的 Golang 微服务 RPC 框架 Kitex。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
Kitex 简介
Kitex 字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选择。 架构设计:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
框架特点:
- 高性能:使用自研的高性能网络库 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 以及脚手架代码。
Thrift 简介
Thrift 本身是一软件框架(远程过程调用框架),用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引 擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。同时,作为 IDL(接口定义语言 Interface Definition Language),允许你定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编译器生成代码用来方便地生成 RPC 客户端和服务器通信的无缝跨编程语言。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
Protobuf 简介
Protobuf 全称是 Google Protocol Buffer,是一种高效轻便的结构化数据存储方式,用于数据的通信协议、数据存储等。相对比 XML 来说,其特点:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
准备环境和快速启动
准备环境
推荐环境:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 如果您之前未搭建 Golang 开发环境, 可以参考 Golang 安装
- 推荐使用最新版本的 Golang,我们保证最新三个正式版本的兼容性(现在 >= )。
- 确保打开 go mod 支持 (Golang >= 时,默认开启)
- kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2
安装教程:Go安装配置 - 掘金 ()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
注意:kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
WSL的安装 由于Kitex并不支持Linux,所以需要首先安装WSL2文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
WSL一句话来说就是微软出的一个虚拟机工具文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
Win11下安装WSL2的步骤为:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- “开始菜单”搜索功能,打开“启动或关闭Window功能”
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 勾选以下功能
3. 微软商店搜索wsl,点击安装文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
4. 安装完打开,安装完之后输入用户的账号密码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
如果安装过程中出现下面这种情况:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
说明内核没有更新,需要更新: 打开一个终端输入以下命令:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
wsl --update
5.安装完成之后输入下列命令查看wsl的状态:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
wsl -l -v
- 启动wsl命令:
wsl
7.安装完成之后我的电脑左下角会出现一个linux盘,为linux子系统的文件系统文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
快速启动
基于 IDL 的 KiteX 实践 在 RPC 框架中,我们知道,服务端与客户端通信的前提是远程通信,但这种通信又存在一种关联,那就是通过一套相关的协议(消息、通信、传输等)来规范,但客户端又不用关心底层的技术实现,只要定义好了这种通信方式即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
在 KiteX 中,也提供了一种生成代码的命令行工具:kitex,目前支持 thrift、protobuf 等 IDL,并且支持生成一个服务端项目的骨架。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 安装 kitex:
go install github.com/cloudwego/kitex/tool/cmd/kitex\@latest
- 安装 thriftgo:
go install github.com/cloudwego/thriftgo\@latest
- 验证是否安装成功:
kitex --version
thriftgo --version
- 获取示例代码
git clone github.com/cloudwego/k…文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 运行示例代码
直接启动:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
cd kitex-examples/hello
go run ./server
go run ./client
使用 Docker 快速启动:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
cd kitex-examples
docker build -t kitex-examples .
docker run --network host kitex-examples ./hello-server
docker run --network host kitex-examples ./hello-client
注:代码生成后的hello/报错,这是因为 这个包使用的是版本的,但之后的包中很多函数增加了context上下文参数,所以很多函数由于缺少参数报错。只需要修改中的require中 为 v0.13.0然后再执行go mod tidy问题就能解决
- 现在成功通过 Kitex 发起了 RPC 调用。增加一个新方法
打开 ,为新方法分别定义一个新的请求和响应,AddRequest 和 AddResponse,并在 service Hello 中增加 add 方法文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
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 工具将根据 更新代码文件文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
kitex -service a.b.c
若当前目录不在 $GOPATH/src 下,需要加上 -module 参数,一般为 下的名字文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
kitex -module "your\_module\_name" -service a.b.c
执行完上述命令后,kitex 工具将更新下述文件文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 更新 ./,在里面增加一个 Add 方法的基本实现
- 更新 ./kitex_gen,里面有框架运行所必须的代码文件
- 更新服务端处理逻辑
- 上述步骤完成后,./ 中会自动补全一个 Add 方法的基本实现,类似如下代码:
func(s \*HelloImpl) Add(ctx , req \*) (resp \*, err error) { return }
在里面增加我们所需要的逻辑,类似如下代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
func(s \*HelloImpl) Add(ctx , req \*) (resp \*, err error) { resp = \&{Sum: req.First + req.Second} return }
- 增加客户端调用
在 ./client/ 中你会看到类似如下的 for 循环:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
for { req := \&{Message: "my request"} resp, err := ((), req) if err != nil { (err) } (resp) () }
在里面增加 Add 方法的调用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
for { req := \&{Message: "my request"} resp, err := ((), req) if err != nil { (err) } (resp) () addReq := \&{First: 512, Second: 512} addResp, err := ((), addReq) if err != nil { (err) } (addResp) () }
- 重新运行示例代码,可以看到客户端在调用 Add 方法
基础教程
Kitex 是一个 RPC 框架,既然是 RPC,底层就需要两大功能:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- Serialization 序列化
- Transport 传输
Kitex 框架及命令行工具,默认支持 thrift 和 proto3 两种 IDL,对应的 Kitex 支持 thrift 和 protobuf 两种序列化协议。 传输上 Kitex 使用扩展的 thrift 作为底层的传输协议(注:thrift 既是 IDL 格式,同时也是序列化协议和传输协议)。IDL 全称是 Interface Definition Language,接口定义语言。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
创建项目目录
在开始后续的步骤之前,先创建一个项目目录用于后续的教程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
mkdir example
然后进入项目目录文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
cd example
编写 IDL
首先创建一个名为 的 thrift IDL 文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
然后在里面定义服务文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
namespace go api
struct Request {
1: string message
}
struct Response {
1: string message
}
service Echo {
Response echo(1: Request req)
}
生成 echo 服务代码
有了 IDL 以后便可以通过 kitex 工具生成项目代码了,执行如下命令:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
$ kitex -module example -service example 上述命令中,-module 表示生成的该项目的 go module 名,-service 表明要生成一个服务端项目,后面紧跟的 example 为该服务的名字。最后一个参数则为该服务的 IDL 文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
生成后的项目结构如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
.
|
|
|
|
| `
| |
| | |
| | |
| | |
| | `
| |
| `
|
`
|
`
获取最新的 Kitex 框架
由于 kitex 要求使用 go mod 进行依赖管理,所以要升级 kitex 框架会很容易,只需要执行以下命令即可:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
go get github.com/cloudwego/kitex@latest$ go mod tidy
编写 echo 服务逻辑
需要编写的服务端逻辑都在 这个文件中,现在这个文件应该如下所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
package main
import (
"context""example/kitex\_gen/api"
)
type EchoImpl struct{}
func(s \*EchoImpl) Echo(ctx , req \*) (resp \*, err error) {
return
}
这里的 Echo 函数就对应了之前在 IDL 中定义的 echo 方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
修改 Echo 函数为下述代码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
func(s \*EchoImpl) Echo(ctx , req \*) (resp \*, err error) {
return \&{Message: }, nil
}
编译运行
kitex 工具已经生成好了编译和运行所需的脚本:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 编译:执行以下命令后,会生成一个 output 目录,里面含有编译产物。
sh build.sh
- 运行:执行以下命令后,Echo 服务就开始运行啦!
sh output/
编写客户端
有了服务端后,接下来编写一个客户端用于调用刚刚运行起来的服务端。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
mkdir client
cd client
import"example/kitex\_gen/api/echo"import""
...
c, err := ("example", (""))
if err != nil {
(err)
}
上述代码中, 用于创建 client,其第一个参数为调用的服务名,要与生成代码中的service_name保持一致,第二个参数为 options,用于传入参数, 此处的 用于指定服务端的地址(server默认占用8888端口)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
import"example/kitex\_gen/api"
...
req := \&{Message: "my request"}
resp, err := ((), req, (3\*))
if err != nil {
(err)
}
(resp)
上述代码中,首先创建了一个请求 req , 然后通过 发起了调用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
- 第一个参数为 ,通过通常用其传递信息或者控制本次调用的一些行为。
- 第二个参数为本次调用的请求。
- 第三个参数为本次调用的 options ,Kitex 提供了一种 callopt 机制,顾名思义——调用参数 ,有别于创建 client 时传入的参数,这里传入的参数仅对此次生效。 此处的 用于指定此次调用的超时(通常不需要指定,此处仅作演示之用)
在编写完一个简单的客户端后,通过下述命令发起调用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
go run
如果不出意外,可以看到类似如下输出:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
2023/01/30 18:48:07 Response({Message:my request})
至此已经成功编写了一个 Kitex 的服务端和客户端,并完成了一次调用!文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
补充:链路追踪
在分布式系统或者微服务架构中,一次请求往往需要调动内部的多个模块,多个中间件,多台机器相互协调才能完成。这些调用过程是较为复杂的,有的是串行调用的,有的是并行调用的。这种情况下,如果确定整个请求当中调用了哪些应用,哪些节点,哪些模块,以及他们的先后顺序和各部分的性能,这就是链路追踪。链路追踪就是将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中展示,比如,各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
Kitex提供了对OpenTelemetry和OpenTracing的支持,也支持用户自定义链路追踪文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
OpenTelemetry链路追踪
import (
...
""""
)
funcmain(){
serviceName := "echo-client"
p := (
(serviceName),
("localhost:4317"),
(),
)
defer p.Shutdown(())
}
svr := (
new(UserServiceImpl),
(()),
(\&{ServiceName: serviceName}),
)
服务注册与发现
Kitex服务注册与发现已经对接了主流的服务注册与发现中心 下面以注册ETCD为例文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html
server:
import (
api "example/kitex\_gen/api/echo""fmt"""""
etcd """log"
)
funcmain() {
r, err := (\[]string{""})
if err != nil {
(err)
}
svr := (new(EchoImpl),
(r),
(\&{
ServiceName: "example",
}),
)
err = ()
if err != nil {
(())
}
}
client
import (
"context""example/kitex\_gen/api""example/kitex\_gen/api/echo""fmt"
client ""
etcd """time"
)
funcmain() {
r, err := (\[]string{""})
if err != nil {
(err)
}
c := ("example",
(r)
)
if err != nil {
(err)
}
for {
ctx, cancel := ((), \*3)
resp, err := (ctx, \&{Message: "hello world!"})
cancel()
if err != nil {
(err)
}
()
(resp)
}
}
总结
本文主要介绍了Golang 微服务 RPC 框架 Kitex 的相关内容,并进行了一个简单的示例演示,本文介绍的都是最基础的入门知识,想更深入学习了解 Kitex 还是需要仔细研究官方文档。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/yunda/45777.html