kitex | 青训营笔记

105 阅读3分钟

kitex初使用| 青训营笔记

这是我参与[第五届青训营] 笔记创作活动的第14天

快速开始

创建项目目录

在开始后续的步骤之前,先让我们创建一个项目目录用于后续的教程

$ mkdir example

然后让我们进入项目目录

$ cd example

Kitex 命令行工具

安装

使用以下命令安装或更新kitex

$ go install github.com/cloudwego/kitex/tool/cmd/kitex

完成后,可以通过执行 kitex 来检测是否安装成功

$ kitex -v

如果出现 command not found 错误,可能是因为没有把 $GOPATH/bin 加入到 $PATH

开始使用

1编写idl

首先我们需要编写一个 IDL,这里以 thrift IDL 为例。首先创建一个名为 echo.thrift 的 thrift IDL 文件。然后在里面定义我们的服务

namespace go api

struct Request {
  1: string message
}

struct Response {
  1: string message
}

service Echo {
    Response echo(1: Request req)
}
复制代码

2 生成 echo 服务代码

有了 IDL 以后我们便可以通过 kitex 工具生成项目代码了,执行如下命令:

$ kitex -module example -service example echo.thrift

上述命令中,-module 表示生成的该项目的 go module 名,-service 表明我们要生成一个服务端项目,后面紧跟的 example 为该服务的名字。最后一个参数则为该服务的 IDL 文件。

eg kitex -module kitex-ex -service api echo.thrift 生成后的项目结构如下:

.
├── build.sh                     // 服务的构建脚本,会创建一个名为 output 的目录并生成启动服务所需的文件到里面
├── handler.go                   // 用户在该文件里实现 IDL service 定义的方法
├── kitex_gen                    // IDL 内容相关的生成代码
│   ├── echo                     // echo.thrift 的生成代码
│   │   ├── base.go              // thriftgo 的产物,包含 echo.thrift 定义的内容的 go 代码
│   │   └── k-base.go            // kitex 在 thriftgo 的产物之外生成的代码
│   └── echo                     // demo.thrift 的生成代码
│       ├── echo.go              // thriftgo 的产物,包含 echo.thrift 定义的内容的 go 代码
│       ├── k-demo.go            // kitex 在 thriftgo 的产物之外生成的代码
│       └── apiservice           // kitex 为 echo.thrift 里定义的 api service 生成的代码
│           ├── apiservice.go    // 提供了 client.go 和 server.go 共用的一些定义
│           ├── client.go        // 提供了 NewClient API
│           └── server.go        // 提供了 NewServer API
├── main.go                      // 程序入口
└── script                       // 构建脚本
    └── bootstrap.sh             // 服务的启动脚本,会被 build.sh 拷贝至 output 下
复制代码

由于 kitex 要求使用 go mod 进行依赖管理,所以我们要升级 kitex 框架会很容易,只需要执行以下命令即可:

$ go mod tidy

3 编写 echo 服务端

我们需要编写的服务端逻辑都在 handler.go 这个文件中,现在这个文件应该如下所示:

package main

import (
  "context"
  "example/kitex_gen/api"
)

// 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 *api.Request) (resp *api.Response, err error) {
  // TODO: Your code here...
  return
}
复制代码

这里的 Echo 函数就对应了我们之前在 IDL 中定义的 echo 方法。

现在让我们修改一下服务端逻辑,让 Echo 服务名副其实。

修改 Echo 函数为下述代码:

func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
  return &api.Response{Message: req.Message}, nil
}
复制代码

4 服务端的编译运行

kitex 工具已经帮我们生成好了编译和运行所需的脚本: 编译: $ sh build.sh 执行上述命令后,会生成一个 output 目录,里面含有我们的编译产物。

运行:

$ sh output/bootstrap.sh

执行上述命令后,Echo 服务就开始运行啦!

5 编写客户端

有了服务端后,接下来就让我们编写一个客户端用于调用刚刚运行起来的服务端。

首先,同样的,先创建一个目录用于存放我们的客户端代码: $ mkdir client

进入目录:$ cd client

创建一个 main.go 文件,然后就开始编写客户端代码了。

6 创建 client

首先让我们创建一个调用所需的 client

import "example/kitex_gen/api/echo"
import "github.com/cloudwego/kitex/client"
...
c, err := echo.NewClient("example", client.WithHostPorts("0.0.0.0:8888"))
if err != nil {
  log.Fatal(err)
}
复制代码

上述代码中,echo.NewClient 用于创建 client,其第一个参数为调用的 服务名,第二个参数为 options,用于传入参数,此处的 client.WithHostPorts 用于指定服务端的地址,更多参数可参考基本特性一节。

7 发起调用

接下来让我们编写用于发起调用的代码:

import "example/kitex_gen/api"
...
req := &api.Request{Message: "my request"}
resp, err := c.Echo(context.Background(), req, callopt.WithRPCTimeout(3*time.Second))
if err != nil {
  log.Fatal(err)
}
log.Println(resp)
复制代码

上述代码中,我们首先创建了一个请求 req , 然后通过 c.Echo 发起了调用。

其第一个参数为 context.Context,通过通常用其传递信息或者控制本次调用的一些行为,你可以在后续章节中找到如何使用它。

其第二个参数为本次调用的请求。

其第三个参数为本次调用的 options ,Kitex 提供了一种 callopt 机制,顾名思义——调用参数 ,有别于创建 client 时传入的参数,这里传入的参数仅对此次生效。 此处的 callopt.WithRPCTimeout 用于指定此次调用的超时(通常不需要指定,此处仅作演示之用)同样的,你可以在 *** 基础特性*** 一节中找到更多的参数。

全部代码如下:

package main  //注意是main

import (
	"context"
	"kitex-ex/kitex_gen/api" //修改为自己的moduel
	"kitex-ex/kitex_gen/api/echo"
	"log"
	"time"

	"github.com/cloudwego/kitex/client"
	"github.com/cloudwego/kitex/client/callopt"
)

func main() {
	c, err := echo.NewClient("example", client.WithHostPorts("0.0.0.0:8888"))
	if err != nil {
		log.Fatal(err)
	}

	req := &api.Request{Message: "my request"}
	resp, err := c.Echo(context.Background(), req, callopt.WithRPCTimeout(3*time.Second))
	if err != nil {
		log.Fatal(err)
	}
	log.Println(resp)
}
复制代码

在客户端的文件夹下执行 $ go run main.go

如果不出意外,你可以看到类似如下输出:

2022/01/28 11:57:35 Response({Message:my request})

至此成功编写了一个 Kitex 的服务端和客户端,并完成了一次调用