Kitex框架入门讲解 | 青训营笔记

166 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

Kitex | RPC框架使用

在我们编程的大多数时候,都需要调用函数。无论是库函数还是自己编写的函数,调用函数的目的都是为了从一个输入得到想要的另一个输入。例如我们需要得到两个数相乘的结果,输入参数是数1和数2,得到的结果是两个数的乘积。但假如我们不想编写自己本地的函数,我们只想“白嫖“,调用其他人电脑上已经编写好的函数,我们就需要通过网络远程调用他写好的函数或者称为方法,这就需要RPC协议的使用。

  • RPC

Remote Procedure Call简称RPC,直译过来就是远程过程调用。在通常写程序的过程中,我们需要调用其他函数时只需要使用函数名并输入参数即可,但当运行于一台计算机的程序调用另一个地址空间的子程序时,就称为远程调用(即通过网络来调用开放网络的计算机上的函数)。RPC通讯协议通过发送请求-接受响应进行信息交互,以一种传统的服务器-客户端的模式完成过程或者说是方法调用。

  • Kitex

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

安装

要注意的一个地方是,github.com/apache/thrift/lib/go/thriftv0.14.0 版本开始提供的 API 和之前的版本是不兼容的,如果在更新依赖的时候给 go get 命令增加了 -u 选项,会导致该库更新到不兼容的版本造成编译失败。你可以通过额外执行一个命令来指定正确的版本:

go get github.com/apache/thrift@v0.13.0

或用replace指令强制固定该版本:

go mod edit -replace github.com/apache/thrift=github.com/apache/thrift@v0.13.0

实例

我们需要远程调用一个函数,我们输入一个字符串,这个函数也给我们返还一个字符串,接下来我们分步来完成这个例子

  • 首先我们新建一个echo.thrift文件,将我们要定义的接口根据thrift语法写好,以下内容定义的一个请求和响应结构体的内容
namespace go api
​
struct Request {
        1: string message
}
​
struct Response {
        1: string message
}
​
service Hello {
    Response echo(1: Request req)
}
  • 运行以下命令一键生成项目代码

    kitex -module example -service example echo.thrift
    
  • 生成了代码之后直接看hander.go文件,其中会有一个Echo函数

    func (s *HelloImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
      // TODO: Your code here...
      return
    }
    
    • req:请求Request结构体指针,即我们定义的包含一个string类型message的结构体
    • resp: 响应Response结构体指针,即我们定义的包含一个string类型message的结构体

    当我们直接返还而不加任何返还参数的时候,根据go语言的语法会返还函数定义中的返还参数,即resperr,由于指针没有附地址,所以此时的resp还是个空指针。我们需要在里面添加一行代码使得返还的结构体中的数据和输入的相同,于是可以直接创建一个Response对象把地址赋给`resp

    // Echo implements the HelloImpl interface.
    func (s *HelloImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
      // TODO: Your code here...
      resp = &api.Response{Message: req.Message}
      return
    }
    
  • 增加一下客户端的调用代码

    服务端已经有了 Echo 方法的处理,现在让我们在客户端增加对 Echo 方法的调用。在新建文件./client/main.go包括新建文件夹:

    package main
    ​
    import (
      "context"
      "example/kitex_gen/api"
      "example/kitex_gen/api/hello"
      "github.com/cloudwego/kitex/client/callopt"
      "log"
      "time"
    )
    import "github.com/cloudwego/kitex/client"func main() {
      c, err := hello.NewClient("example", client.WithHostPorts("0.0.0.0:8888"))
      if err != nil {
        log.Fatal(err)
      }
      for {
        req := &api.Request{Message: "my request"}
        resp, err := c.Echo(context.Background(), req)
        if err != nil {
          log.Fatal(err)
        }
        log.Println(resp)
        time.Sleep(time.Second)
      }
    }
    ​
    

我们每隔一秒发出请求,调用本地服务器的Echo方法,输出返还的结构体。

  • 运行服务器代码

    直接执行kitex生成的脚本编译一下项目

    sh build.sh
    

    然后执行以下代码运行服务器,服务器即在默认端口监听

    sh output/bootstrap.sh
    
  • 运行客户端代码

    另起一个终端,直接运行./client/main.go程序即可

    go run ./client/main.go
    
  • 输出结果

    • 服务器

    截屏2023-01-31 16.14.33.png

    • 客户端

      每隔一秒输出一个结构体

    截屏2023-01-31 16.14.02.png