前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >入门 KiteX 基础篇

入门 KiteX 基础篇

作者头像
程序猿Damon
发布2022-12-05 11:05:30
2.8K0
发布2022-12-05 11:05:30
举报

概览

KiteX 是 bytedance 开源的高性能 RPC 框架,实现了高吞吐、高负载、高性能等居多特性,具体请看 KiteX 的实践,文章介绍多传输协议、消息协议时,说到 KiteX 支持的协议类型:Thrift、Protobuf 等,今天我们主要来实践如何利用 KiteX 基于对应的 IDL 生成对应协议的代码。

Thrift 简介

Thrift 本身是一软件框架(远程过程调用框架),用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引 擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。同时,作为 IDL(接口定义语言 Interface Definition Language),允许你定义一个简单的定义文件中的数据类型和服务接口,以作为输入文件,编译器生成代码用来方便地生成 RPC 客户端和服务器通信的无缝跨编程语言。

Protobuf 简介

Protobuf 全称是 Google Protocol Buffer,是一种高效轻便的结构化数据存储方式,用于数据的通信协议、数据存储等。相对比 XML 来说,其特点:

  • 语言无关,平台无关
  • 高效
  • 扩展性、兼容性更强

基于 IDL 的 KiteX 实践

在 RPC 框架中,我们知道,服务端与客户端通信的前提是远程通信,但这种通信又存在一种关联,那就是通过一套相关的协议(消息、通信、传输等)来规范,但客户端又不用关心底层的技术实现,只要定义好了这种通信方式即可。

在 KiteX 中,也提供了一种生成代码的命令行工具:kitex,目前支持 thrift、protobuf 等 IDL,并且支持生成一个服务端项目的骨架。

安装命令行工具

环境
  • 如果您之前未搭建 Golang 开发环境, 可以参考 Golang 安装
  • 推荐使用最新版本的 Golang,我们保证最新三个正式版本的兼容性(现在 >= v1.16)。
  • 确保打开 go mod 支持 (Golang >= 1.15 时,默认开启)
  • kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2
安装
  • 确保 GOPATH 环境变量已经被正确地定义(例如 export GOPATH=~/go)并且将
GOPATH/bin添加到 PATH 环境变量之中(例如 export PATH=

GOPATH/bin:$PATH);请勿将 GOPATH 设置为当前用户没有读写权限的目录

  • 安装 kitex:go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
  • 安装 thriftgo:go install github.com/cloudwego/thriftgo@latest

安装成功后,执行 kitex --version 可以看到如下信息:

代码语言:javascript
复制
$ kitex --version
v0.4.2

如果在安装阶段发生问题,可能主要是由于对 Golang 的不当使用造成的,需要逐一排查。

编写一个 IDL

我们先新建一个项目:hz-kitex-examples,新建完之后,我们在该项目下新建一个目录:idl,然后我们编写一个 thrift IDL:

接下来,我们编写这个 IDL:

代码语言:javascript
复制
namespace go hello

struct ReqBody {
    1: string name
    2: i32 type
    3: string email
}

struct Request {
 1: string data
 2: string message
 3: ReqBody reqBody
}

struct Msg {
 1: i64 status
 2: i64 code
 3: string msg
}

struct Response {
 1: Msg msg
 2: string data
}

service HelloService {
    Response echo(1: Request req)
    Response testHello4Get(1: Request req)
    Response testHello4Post(1: Request req)
}

这里我们定义了一个命名空间:hello,这个是代表生成的代码中有一个目录:hello,然后我们编写一个请求对象:ReqBody,接着定义一个泛对象,包括了那个请求对象,这块没要求,自己定义好就行,同时我们定义了响应对象Response,此外,我们还定义了一个类,类中存在三个函数方法。

生成代码

在定义完 IDL 后,我们来看如何生成代码呢?直接执行如下命令:

代码语言:javascript
复制
kitex -module "hz-kitex-examples" -thrift frugal_tag -service helloserver idl/hello.thrift

这里有几个参数 tag:

-module module_name

  • 该参数用于指定生成代码所属的 Go 模块,会影响生成代码里的 import path。
  • 如果当前目录是在
GOPATH/src 下的一个目录,那么可以不指定该参数;kitex 会使用

GOPATH/src 开始的相对路径作为 import path 前缀。例如,在 $GOPATH/src/example.com/hello/world 下执行 kitex,那么 kitex_gen/example_package/example_package.go 在其他代码代码里的 import path 会是 example.com/hello/world/kitex_gen/example_package。

  • 如果当前目录不在 $GOPATH/src 下,那么必须指定该参数。
  • 如果指定了 -module 参数,那么 kitex 会从当前目录开始往上层搜索 go.mod 文件
    • 如果不存在 go.mod 文件,那么 kitex 会调用 go mod init 生成 go.mod;
    • 如果存在 go.mod 文件,那么 kitex 会检查 -module 的参数和 go.mod 里的模块名字是否一致,如果不一致则会报错退出;
    • 最后,go.mod 的位置及其模块名字会决定生成代码里的 import path。

-service service_name

  • 使用该选项时,kitex 会生成构建一个服务的脚手架代码,参数 service_name 给出启动时服务自身的名字,通常其值取决于使用 Kitex 框架时搭配的服务注册和服务发现功能。

对于当前项目,我们执行如下:

代码语言:javascript
复制
kitex -module "hz-kitex-examples" -thrift frugal_tag -service helloserver idl/hello.thrift

由于当前项目不在环境路径下,需要指定 go.mod 所在的目录模块的名称,同时,我们指定一个服务名。

这样在执行后,我们会发现生成的目录结构如下图:

在生成的目录中根目录是kitex_gen,代表是 kitex 工具生成的,其次其目录下有一个 hello 目录,这是代表 IDL 文件中的 ns,在其下面有一个文件:定义了请求对象与响应对象的序列化、传输信息的读写等操作。

在其下面还存在一个 service 目录,用来生成跟客户端与服务端相关的 service 处理逻辑。其中也定义了 service 中处理的方法信息。

同时,我们可以看到生成了服务端的基础框架:

服务端

新建一个server 目录,然后在里面新建一个项目hello,此时把生成服务端的骨架代码拷贝到里面:

拷贝完之后,我们可以丰满服务端的函数的逻辑,以 Echo 函数为例:

代码语言:javascript
复制
func (s *HelloApi) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {
 klog.Info("hello service enter: " + GetIpAddr2())

 resp = &api.Response {
  Msg:  &api.Msg {
   Status: 200,
   Code:   10000,
   Msg:    req.Message,
  },
  Data: req.Message,
 }
 return resp, nil
}

func GetIpAddr2() string {
 conn, err := net.Dial("udp", "8.8.8.8:53")
 if err != nil {
  klog.Error(err)
  return ""
 }
 localAddr := conn.LocalAddr().(*net.UDPAddr)
 // 192.168.1.20:61085
 ip := strings.Split(localAddr.String(), ":")[0]

 return ip
}

然后再定义启动函数:

代码语言:javascript
复制
svr := hello.NewServer(new(api.HelloApi),
    server.WithServiceAddr(&net.TCPAddr{Port: 2008}),
  server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: constants.HelloServiceName}),
    server.WithPayloadCodec(thrift.NewThriftCodecWithConfig(thrift.FastRead | thrift.FastWrite)),
  server.WithErrorHandler(func(err error) error {
   error := errno.ConvertErr(err)
   return error
  }),
  //指定默认 Codec 的包大小限制,默认无限制 option: codec.NewDefaultCodecWithSizeLimit
  server.WithCodec(codec.NewDefaultCodecWithSizeLimit(1024 * 1024 * 10)),//10M
  server.WithLimit(&limit.Option{MaxConnections: 10000, MaxQPS: 5000}),
  //连接多路复用(mux)
  server.WithMuxTransport(),
  server.WithMetaHandler(transmeta.ServerTTHeaderHandler),
  server.WithRegistry(registry.NewNacosRegistry(r1)),
 )

在这里,我们定义了服务端的端口:2008,同时被注册到 Nacos。启动之后:

可以看到被注册到 Nacos:

这里注册 Nacos 的代码前面已经讲过了,具体可以看:KiteX 的实践

客户端

关于客户端,也是一样,新建一个 client 目录,里面新建一个项目customer-service,新建启动 main 函数,这里与服务端类似不再赘述了。主要注意一点:这里由于需要提供 Http 协议接口,需要结合 Hertz 来进行:

至于 Hertz,它是一个高性能的 Http 微服务框架在后面的文章中会进一步讲解,此处不再赘述。

启动函数新建完后,我们需要初始化一个 RPC 连接的客户端:

此处客户端的初始化,也是基于之前生成的代码:

在这个函数初始化客户端时,需要定义请求的服务名、网络库、负载均衡策略、出错误处理机制等。同时,我们还需要复写需要调用的函数,去调用相关的接口:

写完 RPC 的部分,一个简单的 RPC 协议调用就能串联起来了,此时,我们来简单写下客户端的接口调用:

代码语言:javascript
复制
func HelloDemo(ctx context.Context, c *app.RequestContext) {
 req := &api.Request{Message: "my request"}
  // TODO
 resp, err := rpc.Echo(context.Background(), req)
 if err != nil {
  log.Fatal(err)
 }
 klog.Info(resp)
  // TODO
 c.JSON(consts.StatusOK, (resp))
}

上面定义的是客户端的接口入口,进入后,会调用 rpc 的部分。同时在调用 RPC 前后,可以有自己的逻辑处理以及响应数据的处理,在 TODO 部分。

启动客户端进行服务注册:

测试

在启动完服务端、客户端后,我们访问客户端的 http 接口:

代码语言:javascript
复制
http://192.168.6.51:3000/v1/hello/test

我们再多几次进行访问:

发现其访问的性能以及速度还是不错的,这得益于 KiteX 框架中使用了自研的 Netpoll 网络库以及实现了高效的吞吐编解码性能提升。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 交个朋友之猿天地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概览
  • Thrift 简介
  • Protobuf 简介
  • 基于 IDL 的 KiteX 实践
    • 安装命令行工具
      • 环境
      • 安装
    • 编写一个 IDL
      • 生成代码
        • 服务端
          • 客户端
            • 测试
            相关产品与服务
            命令行工具
            腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档