开源 Golang 微服务入门二:RPC 框架 Kitex

这篇具有很好参考价值的文章主要介绍了开源 Golang 微服务入门二:RPC 框架 Kitex。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

开源 Golang 微服务入门二:RPC 框架 Kitex

前言

前一篇笔记介绍了字节跳动的开源 Golang 微服务 HTTP 框架 Hertz,
如下:
开源 Golang 微服务入门一: HTTP 框架 Hertz

本文将要介绍同样是字节跳动开源的 Golang 微服务 RPC 框架 Kitex。

Kitex 简介

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

开源 Golang 微服务入门二:RPC 框架 Kitex

框架特点:

  • 高性能:使用自研的高性能网络库 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 客户端和服务器通信的无缝跨编程语言。

Protobuf 简介

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

  • 语言无关,平台无关

  • 高效

  • 扩展性、兼容性更强

准备环境和快速启动

准备环境

推荐环境:

  • 如果您之前未搭建 Golang 开发环境, 可以参考 Golang 安装

  • 推荐使用最新版本的 Golang,我们保证最新三个正式版本的兼容性(现在 >= v1.16)。

  • 确保打开 go mod 支持 (Golang >= 1.15 时,默认开启)

  • kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2

安装教程:2023年最新无脑安装 Go lang 环境配置并编写、运行、打包第一个 Golang 程序详细步骤,附带图文教程

注意:kitex 暂时没有针对 Windows 做支持,如果本地开发环境是 Windows 建议使用 WSL2

WSL的安装
由于Kitex并不支持Linux,所以需要首先安装WSL2

WSL一句话来说就是微软出的一个虚拟机工具

Win11下安装WSL2的步骤为:

  1. “开始菜单”搜索功能,打开“启动或关闭Window功能”

开源 Golang 微服务入门二:RPC 框架 Kitex

  1. 勾选以下功能
  • 适用于Linux的Window子系统
  • 虚拟机平台

开源 Golang 微服务入门二:RPC 框架 Kitex
3. 微软商店搜索wsl,点击安装

开源 Golang 微服务入门二:RPC 框架 Kitex
4. 安装完打开,安装完之后输入用户的账号密码

开源 Golang 微服务入门二:RPC 框架 Kitex
如果安装过程中出现下面这种情况:

开源 Golang 微服务入门二:RPC 框架 Kitex
说明内核没有更新,需要更新:
打开一个终端输入以下命令:

wsl --update

5.安装完成之后输入下列命令查看wsl的状态:

wsl -l -v
  1. 启动wsl命令:
wsl

7.安装完成之后我的电脑左下角会出现一个linux盘,为linux子系统的文件系统

开源 Golang 微服务入门二:RPC 框架 Kitex

快速启动

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

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

  1. 安装 kitex:
go install github.com/cloudwego/kitex/tool/cmd/kitex\@latest
  1. 安装 thriftgo:
go install github.com/cloudwego/thriftgo\@latest
  1. 验证是否安装成功:
  • kitex --version
  • thriftgo --version
  1. 获取示例代码

git clone https://github.com/cloudwego/kitex-examples.git

  1. 运行示例代码

    直接启动:

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

    使用 Docker 快速启动:

    • 进入示例仓库目录
    cd kitex-examples
    
    • 编译项目
    docker build -t kitex-examples .
    
    • 运行 server
    docker run --network host kitex-examples ./hello-server
    
    • 运行 client:另起一个终端后
    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问题就能解决

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

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

    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)
    }
    
  3. 重新生成代码

    运行如下命令后,kitex 工具将根据 hello.thrift 更新代码文件

    kitex -service a.b.c hello.thrift
    

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

    kitex -module "your\_module\_name" -service a.b.c hello.thrift
    

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

    • 更新 ./handler.go,在里面增加一个 Add 方法的基本实现

    • 更新 ./kitex_gen,里面有框架运行所必须的代码文件

    • 更新服务端处理逻辑

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

    // 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
    }
    

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

    // 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
    }
    
  5. 增加客户端调用

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

    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 方法的调用:

    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)
    }
    
  6. 重新运行示例代码,可以看到客户端在调用 Add 方法

基础教程

Kitex 是一个 RPC 框架,既然是 RPC,底层就需要两大功能:

  • Serialization 序列化

  • Transport 传输

Kitex 框架及命令行工具,默认支持 thrift 和 proto3 两种 IDL,对应的 Kitex 支持 thrift 和 protobuf 两种序列化协议。 传输上 Kitex 使用扩展的 thrift 作为底层的传输协议(注:thrift 既是 IDL 格式,同时也是序列化协议和传输协议)。IDL 全称是 Interface Definition Language,接口定义语言。

创建项目目录

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

mkdir example

然后进入项目目录

 cd example

编写 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)
}

生成 echo 服务代码

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

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

生成后的项目结构如下:

    .
    |-- build.sh
    |-- echo.thrift
    |-- handler.go
    |-- kitex_gen
    |   `-- api
    |       |-- echo
    |       |   |-- client.go
    |       |   |-- echo.go
    |       |   |-- invoker.go
    |       |   `-- server.go
    |       |-- echo.go
    |       `-- k-echo.go
    |-- main.go
    `-- script
        |-- bootstrap.sh
        `-- settings.py

获取最新的 Kitex 框架

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

go get github.com/cloudwego/kitex@latest$ go mod tidy
编写 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 函数为下述代码:

func (s \*EchoImpl) Echo(ctx context.Context, req \*api.Request) (resp \*api.Response, err error) {
    return \&api.Response{Message: req.Message}, nil
}
编译运行

kitex 工具已经生成好了编译和运行所需的脚本:

  • 编译:执行以下命令后,会生成一个 output 目录,里面含有编译产物。
sh build.sh
  • 运行:执行以下命令后,Echo 服务就开始运行啦!
sh output/bootstrap.sh
编写客户端

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

  • 创建一个目录用于存放客户端代码:
mkdir client
  • 进入目录:
cd 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,其第一个参数为调用的服务名,要与生成代码中的service_name保持一致,第二个参数为 options,用于传入参数, 此处的 client.WithHostPorts 用于指定服务端的地址(server默认占用8888端口)。

  • 发起调用
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 用于指定此次调用的超时(通常不需要指定,此处仅作演示之用)

在编写完一个简单的客户端后,通过下述命令发起调用:

go run main.go

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

2023/01/30 18:48:07 Response({Message:my request})

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

补充:链路追踪

在分布式系统或者微服务架构中,一次请求往往需要调动内部的多个模块,多个中间件,多台机器相互协调才能完成。这些调用过程是较为复杂的,有的是串行调用的,有的是并行调用的。这种情况下,如果确定整个请求当中调用了哪些应用,哪些节点,哪些模块,以及他们的先后顺序和各部分的性能,这就是链路追踪。链路追踪就是将一次分布式请求还原成调用链路,将一次分布式请求的调用情况集中展示,比如,各个服务节点上的耗时、请求具体到达哪台机器上、每个服务节点的请求状态等。

Kitex提供了对OpenTelemetry和OpenTracing的支持,也支持用户自定义链路追踪

OpenTelemetry链路追踪

import (
...
    "github.com/kitex-contrib/obs-opentelemetry/provider"
    "github.com/kitex-contrib/obs-opentelemetry/tracing"
)

func main(){
    serviceName := "echo-client"

    //接入OpenTelemetry
    p := provider.NewOpenTelemetryProvider(
        provider.WithServiceName(serviceName),
        provider.WithExportEndpoint("localhost:4317"),
        provider.WithInsecure(),
    )
    defer p.Shutdown(context.Background())

}

svr := userservice.NewServer(
    new(UserServiceImpl),
    //注入trace到server实例中
    server.WithSuite(tracing.NewServerSuite()),
    server.WithServerBasicInfo(\&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}),
)

服务注册与发现

Kitex服务注册与发现已经对接了主流的服务注册与发现中心
下面以注册ETCD为例

server:
import (
    api "example/kitex\_gen/api/echo"
    "fmt"
    "github.com/cloudwego/kitex/pkg/rpcinfo"
    "github.com/cloudwego/kitex/server"
    etcd "github.com/kitex-contrib/registry-etcd"
    "log"
)

func main() {
    r, err := etcd.NewEtcdRegistry(\[]string{"127.0.0.1:2379"})
    //创建一个etcd的注册,ectd占127.0.0.1的2379端口
        if err != nil {
            fmt.Println(err)
        }
        svr := api.NewServer(new(EchoImpl),
        server.WithRegistry(r), //将server注册到etcd中
        server.WithServerBasicInfo(\&rpcinfo.EndpointBasicInfo{
        ServiceName: "example",
    }),
    )

    err = svr.Run()

    if err != nil {
        log.Println(err.Error())
    }
}
client
import (
    "context"
    "example/kitex\_gen/api"
    "example/kitex\_gen/api/echo"
    "fmt"
    client "github.com/cloudwego/kitex/client"
    etcd "github.com/kitex-contrib/registry-etcd"
    "time"
)

func main() {
    //根据127.0.0.1:2379地址创建一个etcd组件实例
    r, err := etcd.NewEtcdResolver(\[]string{"127.0.0.1:2379"})
    if err != nil {
        fmt.Println(err)
    }
    c := echo.MustNewClient("example",
    client.WithResolver(r)//client.WithResolver,我们能看到最后把一个服务发现实例放到了 client 的 options 结构体中:
    )
    if err != nil {
        fmt.Println(err)
    }
    for {
        ctx, cancel := context.WithTimeout(context.Background(), time.Second\*3)
        resp, err := c.Echo(ctx, \&api.Request{Message: "hello world!"})
        cancel()
        if err != nil {
            fmt.Println(err)
        }
        time.Sleep(time.Second)
        fmt.Println(resp)
    }
}

总结

本文主要介绍了Golang 微服务 RPC 框架 Kitex 的相关内容,并进行了一个简单的示例演示,本文介绍的都是最基础的入门知识,想更深入学习了解 Kitex 还是需要仔细研究官方文档。文章来源地址https://www.toymoban.com/news/detail-486592.html

引用

  • Kitex 官方文档 Kitex | CloudWeGo

到了这里,关于开源 Golang 微服务入门二:RPC 框架 Kitex的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 Hertz 和 Kitex 的 Go 微服务项目 | 开源项目推荐

    FreeCar 是一个基于 Hertz 与 Kitex 的全栈微服务项目,欢迎 Star。 项目地址:CyanAsterisk/FreeCar Hertz 是一个超大规模的企业级微服务 HTTP 框架,具有高易用性、易扩展、低时延等特点。 Hertz 默认使用自研的高性能网络库 Netpoll,在一些特殊场景中,相较于 go net,Hertz 在 QPS、时延上

    2024年02月07日
    浏览(25)
  • 14 | 开源RPC框架如何选型?

    专栏第 6 期讲解了 RPC 远程调用的原理,简单回顾一下一个完整的 RPC 框架主要有三部分组成:通信框架、通信协议、序列化和反序列化格式。根据我的经验,想要开发一个完整的 RPC 框架,并且应用到线上生产环境,至少需要投入三个人力半年以上的时间。这对于大部分中小

    2024年02月02日
    浏览(32)
  • Golang 实现一个简单的 RPC 服务

    分享一个简单的 rpc 服务框架 一、服务端实现 二、客户端实现

    2024年04月10日
    浏览(35)
  • SpringBoot篇——SpringBoot微服务理解、SpringBoot和SSM框架区别等技术点,带你入门SpringBoot,一篇搞定!

    一、什么是为微服务 微服务是一种 架构风格 ,打破了all in one的架构方式,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合。 可以通过http的方式进行互通,服务可以独立部署和扩展,每个服务都提供一个坚实的模块边界,甚至不同的服务可以用

    2024年02月04日
    浏览(27)
  • 深入剖析gRPC:Google开源的高性能RPC框架

    在本篇文章中,我们将深入剖析gRPC,Google开源的高性能RPC框架。gRPC是一种基于HTTP/2的高性能、可扩展的RPC框架,它使用Protocol Buffers作为接口定义语言,可以在多种编程语言之间实现无缝通信。 gRPC的核心设计理念是:通过使用HTTP/2作为传输协议,实现高效、可扩展的RPC通信

    2024年02月19日
    浏览(38)
  • 国内首个基于 Rust 语言的 RPC 框架 — Volo 正式开源!

    Volo 是字节跳动服务框架团队研发的 轻量级 、 高性能 、 可扩展性强 、 易用性好 的 Rust RPC 框架,使用了 Rust 最新的 GAT 和 TAIT 特性。 在字节内部,Volo 已经落地多个业务和基础组件,并且取得了超预期的性能收益(与 Go 版本对比,不那么公平)。 Volo 与其它 CloudWeGo 开源项

    2023年04月16日
    浏览(25)
  • Golang入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

    文章目录 一、golang 简介 1. go 语言特点 2. go 语言应用领域 3. 使用 go 语言的公司有哪些 二、安装 golang 1. golang 下载安装 2. 配置环境变量 三、golang 开发工具 1. 安装 VSCode 2. 下载所需插件 四、第一个 golang 应用 1. main 包的含义 2. 示例 Go 是一个开源的编程语言,它能让构造简单

    2024年02月04日
    浏览(32)
  • 【Golang入门教程】Goland常用快捷键,看这一篇就够了

    强烈推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站: 人工智能 前言 在进行Go语言开发时,熟练使用快捷键是提高效率、加快编码速度的关键。 Goland作为一款强大的集成开发环境(IDE),提供了丰富的快捷键

    2024年02月20日
    浏览(41)
  • 14-RPC-自研微服务框架

    RPC 框架是分布式领域核心组件,也是微服务的基础。 RPC (Remote Procedure Call)全称是远程过程调用,相对于本地方法调用,在同一内存空间可以直接通过方法栈实现调用,远程调用则跨了不同的服务终端,并不能直接调用。 RPC框架 要解决的就是远程方法调用的问题,并且实

    2024年03月08日
    浏览(39)
  • RPC框架引入zookeeper服务注册与服务发现

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是大数据生态中的重要组件。它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提

    2024年02月14日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包