字节跳动rpc框架——Kitex初探感悟

简介

Kitex 字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选择。

Kitex 的架构主要包括四个部分:Kitex Tool、Kitex Core、Kitex Byted、Second Party Pkg。

  • Kitex Core 是一个携带了一套微服务治理功能的 RPC 框架,它是 Kitex 的核心部分。
  • Kitex Byted 是一套结合了字节跳动内部基础设施的拓展集合。通过这一套拓展集合,Kitex 能够在内部支持业务的发展。
  • Kitex Tool 是一个命令行工具,能够在命令行生成我们的代码以及服务的脚手架,可以提供非常便捷的开发体验。
  • Second Party Pkg,例如 netpoll, netpoll-http2,是 Kitex 底层的网络库,这两个库也开源在 CloudWeGo 组织中。

Kite 作为字节跳动第一代 Golang RPC 框架,主要存在以下缺陷:

  1. Kite 为了快速支持业务发展需求,不可避免地耦合了部分中台业务的功能;
  2. Kite 对 Go modules 支持不友好(Go modules 在 2019 年才进入语言核心);
  3. Kite 自身的代码拆分成多仓库,版本更新时推动业务升级困难;
  4. Kite 强耦合了早期版本的 Apache Thrift,协议和功能拓展困难;
  5. Kite 的生成代码逻辑与框架接口强耦合,成为了性能优化的天花板。

因此,业务的快速发展和需求场景的多样化,催生了新一代 Golang RPC 框架 Kitex。

使用

安装

目前kitex还没有支持Windows系统,所以对于Windows的用户,需要安装虚拟机。虚拟机软件可以选择VirtualBox或者Vmware。 在搭建好golang环境后,进入kitex的官方文档,安装kitex与thriftgo命令行工具。

bash 复制代码
go install github.com/cloudwego/kitex/tool/cmd/kitex\@latest # 安装kitex
go install github.com/cloudwego/thriftgo\@latest # 安装thrift

这里需要注意,如果没有将GOPATH/bin添加到环境变量的话,安装后的命令行工具是无法用的。 可以使用go env查看GOPATH路径。

bash 复制代码
export PATH=$PATH:$GOPATH/bin # 添加$GOPATH/bin到系统环境变量

如果不想每次都重新设置环境变量,可以在~/.bashrc文件末尾追加上述指令。

验证是否安装成功

bash 复制代码
kitex --version
thriftgo --version

例程

获取示例代码

git clone github.com/cloudwego/k...

运行示例代码

直接启动:

  • 进入示例仓库的 hello 目录
bash 复制代码
cd kitex-examples/hello
  • 运行 server
arduino 复制代码
go run ./server
  • 运行 client:另起一个终端后
arduino 复制代码
go run ./client

使用 Docker 快速启动:

  • 进入示例仓库目录
bash 复制代码
cd kitex-examples
  • 编译项目
erlang 复制代码
docker build -t kitex-examples .
  • 运行 server
arduino 复制代码
docker run --network host kitex-examples ./hello-server
  • 运行 client:另起一个终端后
arduino 复制代码
docker run --network host kitex-examples ./hello-client

注:代码生成后的hello/hello.go报错,这是因为github.com/apache/thrift 这个包使用的是v0.17.0版本的,但v0.14.0之后的包中很多函数增加了context上下文参数,所以很多函数由于缺少参数报错。只需要修改go.mod中的require中github.com/apache/thrift v0.17.0为github.com/apache/thrift v0.13.0然后再执行go mod tidy问题就能解决

现在成功通过 Kitex 发起了 RPC 调用。增加一个新方法

打开 hello.thrift,为新方法分别定义一个新的请求和响应,AddRequest 和 AddResponse,并在 service Hello 中增加 add 方法

go 复制代码
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 工具将根据 hello.thrift 更新代码文件

css 复制代码
kitex -service a.b.c hello.thrift

若当前目录不在 $GOPATH/src 下,需要加上 -module 参数,一般为 go.mod 下的名字

arduino 复制代码
kitex -module "your_module_name" -service a.b.c hello.thrift

执行完上述命令后,kitex 工具将更新下述文件

  • 更新 ./handler.go,在里面增加一个 Add 方法的基本实现
  • 更新 ./kitex_gen,里面有框架运行所必须的代码文件
  • 更新服务端处理逻辑

上述步骤完成后,./handler.go 中会自动补全一个 Add 方法的基本实现,类似如下代码:

go 复制代码
// 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
}

在里面增加我们所需要的逻辑,类似如下代码:

go 复制代码
// Add implements the HelloImpl interface.
func (s *HelloImpl) Add(ctx context.Context, req *api.AddRequest) (resp *api.AddResponse, err error) {
    // TODO: Your code here...
    resp = &api.AddResponse{Sum: req.First + req.Second}
    return
}

增加客户端调用

在 ./client/main.go 中你会看到类似如下的 for 循环:

css 复制代码
for {
    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)
}

在里面增加 Add 方法的调用:

css 复制代码
for {
    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)
    addReq := &api.AddRequest{First: 512, Second: 512}
    addResp, err := client.Add(context.Background(), addReq)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(addResp)
    time.Sleep(time.Second)
}

重新运行示例代码,可以看到客户端在调用 Add 方法

总结

总的来说,kitex框架降低了我们开发rpc服务的工作量,通过自动生成代码的方式,避免了重复的工作。然而在实际使用时也存在了一定的不便。自动生成模型时,无法携带结构体的tag标签,使得与gin等web框架结合使用时,无法使用参数帮等功能。虽然可以通过手动修改生成文件的方式来实现,但是这样一来,如果需要重新生成代码时,工作量又会上升。最后,希望kitex框架越做越好。

相关推荐
希冀12320 分钟前
【操作系统】1.2操作系统的发展与分类
后端
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
serve the people2 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端
罗政7 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
拾光师9 小时前
spring获取当前request
java·后端·spring
Java小白笔记10 小时前
关于使用Mybatis-Plus 自动填充功能失效问题
spring boot·后端·mybatis
JOJO___12 小时前
Spring IoC 配置类 总结
java·后端·spring·java-ee
白总Server13 小时前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php
Lingbug14 小时前
.Net日志组件之NLog的使用和配置
后端·c#·.net·.netcore