【字节青训营-7】:初探 Kitex 字节微服务框架(使用ETCD进行服务注册与发现)

本文目录

  • 一、Kitex概述
  • 二、第一个Kitex应用
  • 三、IDL
  • 四、服务注册与发现

一、Kitex概述

长话短说,就是字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。

如果对微服务性能有要求,又希望定制扩展融入自己的治理体系,Kitex 会是一个不错的选择。

可以看到下面是Kitex的架构设计。

在这里插入图片描述
这个框架有一些特点,比如:

  • 高性能

使用自研的高性能网络库 Netpoll,性能相较 go net 具有显著优势。

  • 扩展性

提供了较多的扩展接口以及默认扩展实现,使用者也可以根据需要自行定制扩展,具体见下面的框架扩展。

  • 多消息协议

RPC 消息协议默认支持 Thrift、Kitex Protobuf、gRPC。Thrift 支持 Buffered 和 Framed 二进制协议,与支持原生 Thrift 协议的多语言框架都能互通; Kitex Protobuf 是 Kitex 自定义的 Protobuf 消息协议,协议格式类似 Thrift;gRPC 是对 gRPC 消息协议的支持,可以与 gRPC 互通。除此之外,使用者也可以扩展自己的消息协议,目前社区也提供了 Dubbo 协议的支持,可以与 Dubbo 互通。

  • 多传输协议

传输协议封装消息协议进行 RPC 互通,传输协议可以额外透传元信息,用于服务治理,Kitex 支持的传输协议有 TTHeader、HTTP2。TTHeader 可以和 Thrift、Kitex Protobuf 结合使用;HTTP2 目前主要是结合 gRPC 协议使用,后续也会支持 Thrift。

  • 多种消息类型

支持 PingPong、Oneway、双向 Streaming。其中 Oneway 目前只对 Thrift 协议支持,双向 Streaming 只对 gRPC 支持,后续会考虑支持 Thrift 的双向 Streaming。

  • 服务治理

支持服务注册/发现、负载均衡、熔断、限流、重试、监控、链路跟踪、日志、诊断等服务治理模块,大部分均已提供默认扩展,使用者可选择集成。

  • 代码生成

Kitex 内置代码生成工具,可支持生成 Thrift、Protobuf 以及脚手架代码。

二、第一个Kitex应用

首先我们创建一个新的Go项目,然后安装对应的插件:kitexthriftgo

然后在终端输入对应的安装命令:

go install github.com/cloudwego/kitex/tool/cmd/kitex@latest
go install github.com/cloudwego/thriftgo@latest

然后等待对应的安装即可。

在项目路径下安装新建thrift文件,然后输入如下代码:

在这里插入图片描述

namespace go apistruct Request{1:string message
}struct Response{1:string message
}service Echo{Response echo(1:Request req)
}

简单来说,这段代码定义一个简单的服务 Echo,它包含一个方法 echo。这个方法接收一个 Request 类型的对象作为输入,处理后返回一个 Response 类型的对象。Request 和 Response 都包含一个字符串字段 message,分别用于传递请求消息和响应消息。这种定义方式使得 Thrift 可以生成不同语言的代码(例如 Go、Java、Python 等),方便跨语言的服务调用。

然后在命令行输入命令:

kitex -module exampleKitex -service exampleKitex echo.thrift

来生成基本的代码。

在这里插入图片描述
等待一会后,可以看到目录已经更新了。

在这里插入图片描述
在这里插入图片描述
main.go中输入如下代码:

package mainimport (api "exampleKitex/kitex_gen/api/echo""log"
)
/*api.NewServer 是一个函数,用于创建一个新的服务实例。new(EchoImpl) 创建了一个 EchoImpl 类型的实例,并将其传递给 api.NewServer。调用 svr.Run() 方法启动服务。
*/
func main() {svr := api.NewServer(new(EchoImpl))err := svr.Run()if err != nil {log.Println(err.Error())}
}

如果有报错,可以输入go mod tidy来补充对应需要的库。

然后在handler.go中来输入逻辑代码。

(s *EchoImpl):这是方法的接收者,表示这个方法属于 EchoImpl 类型的指针 s。
EchoImpl 是一个结构体类型,通常是由 Thrift 生成的接口的具体实现。
echo是方法名称,对应 Thrift 定义中的 echo 方法。
ctx context.Context:这是方法的第一个参数,类型为 context.Context。
context 是 Go 标准库中的一个包,用于在程序中传递上下文信息,例如超时、取消信号等。
req *api.Request:这是方法的第二个参数,类型为 *api.Request,表示这是一个指向 api.Request 类型的指针。
api.Request 是 Thrift 定义的 Request 结构体,通过 Thrift 生成的 Go 代码中的 api 包来访问。&api.Response{}:创建了一个 api.Response 类型的实例,并取其地址(返回一个指针)。
Message: req.Message:将 req 参数中的 Message 字段值赋给新创建的 Response 实例的 Message 字段。这是一个简单的回显服务,即客户端发送一个消息,服务端原样返回这个消息。
package mainimport ("context"api "exampleKitex/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 &api.Response{Message: req.Message}, nil
}

然后我们来启动main.go和handler.go. 启动之后会默认在监听端口进行对应的监听。

在这里插入图片描述

然后我们新建一个客户端,并且写入对应的客户端代码。

package mainimport ("context""github.com/cloudwego/kitex/client/callopt""log""exampleKitex/kitex_gen/api""exampleKitex/kitex_gen/api/echo""time"
)import "github.com/cloudwego/kitex/client"func main() {//下面的destService对应服务名称是我们在启动kitex代码生成工具命令中的service名称// kitex -moudle exampleKitex -service exampleKitex(服务名称) echo.thriftc, err := echo.NewClient("exampleKitex", 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 .\client.go即可。

然后可以看到返回的Response如下:

在这里插入图片描述

所以总结一下,就是,先在echo.thrift中编写接口,定义发送什么样的请求,请求里边有什么样的一个信息,然后就是继续定义一个响应,以及服务的逻辑。

在这里插入图片描述

三、IDL

IDL(Interface Definition Language,接口定义语言)是一种用于定义软件组件之间交互接口的规范语言。它允许开发者以一种语言无关的方式描述服务接口、数据结构和通信协议,从而实现不同编程语言之间的互操作性。IDL 的核心目的是提供一种标准化的方式来定义服务的接口和数据结构,使得这些接口和数据结构可以在多种编程语言中被实现和使用。

IDL就是我们刚刚定义的这个thrift文件。

如果进行PRC,那么就需要知道对方的接口是什么,需要传什么参数,也需要知道返回值是什么样子的。这个时候就需要通过IDL来约定双方的协议。就像调用某个函数,需要知道函数签名一样。

定义好thrift文件之后,就可以使用命令生成代码了。
kitex -module example -service example echo.thrift生成代码。

在这里插入图片描述

服务是默认监听8888端口的。

四、服务注册与发现

目前Kitex的服务注册与发现已经对接了主流的服务注册与发现中心,如ETCD、Nacos、zookeeper、Eureka等。

接下来我们进行一个简单的实战。

首先我们下载etcd:https://github.com/etcd-io/etcd/releases,找到对应的电脑的版本。

在这里插入图片描述

下载好之后找个文件夹进行解压缩,然后打开,双击打开即可。

在这里插入图片描述

运行起来之后可以看到对应的2380和2379两个端口。

在这里插入图片描述
到这一步,服务器已经启用成功了。

接下来我们需要把服务注册到etcd注册中心去。修改handler.go的相关代码。

简单说明下作用:实现一个 Kitex 服务端程序,通过 ETCD 注册中心将自身注册为一个可发现的服务,并提供了一个简单的 Echo 方法。程序的主要功能包括:

package mainimport ("context"api "exampleKitex/kitex_gen/api""exampleKitex/kitex_gen/api/echo""github.com/cloudwego/kitex/pkg/rpcinfo""github.com/cloudwego/kitex/server"etcd "github.com/kitex-contrib/registry-etcd""log"
)// EchoImpl implements the last service interface defined in the IDL.EchoImpl:定义了一个结构体,用于实现服务接口。
type EchoImpl struct{}// Echo implements the EchoImpl interface.
// ctx context.Context:上下文对象,用于传递超时和取消信号。
// req *api.Request:请求对象,包含客户端发送的数据。
func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Response, err error) {// TODO: Your code here...return &api.Response{Message: req.Message}, nil}func main() {//etcd.NewEtcdRegistry:创建一个 ETCD 注册中心实例。//参数 []string{"127.0.0.1:2379"} 指定了 ETCD 服务的地址。r, err := etcd.NewEtcdRegistry([]string{"127.0.0.1:2379"})if err != nil {log.Fatal(err)}//echo.NewServer:创建一个服务实例。//new(EchoImpl):创建一个 EchoImpl 实例,作为服务的具体实现。//server.WithRegistry(r):指定使用 ETCD 注册中心实例 r,将服务注册到 ETCD 中。//server.WithServerBasicInfo:设置服务的基本信息,例如服务名称。ServiceName: "Hello":将服务名称设置为 "Hello",客户端可以通过这个名称找到服务。server := echo.NewServer(new(EchoImpl), server.WithRegistry(r), server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: "Hello",}))err = server.Run()if err != nil {log.Fatal(err)}}

同时我们修改client.go的代码如下:

一句话概括下作用,就是:使用 Kitex 框架的客户端程序,通过 ETCD 注册中心动态发现服务,并调用名为 Hello 的服务的 Echo 方法。代码的主要功能是定期发送请求到服务端,并打印响应结果。

package mainimport ("context""exampleKitex/kitex_gen/api""exampleKitex/kitex_gen/api/echo""github.com/cloudwego/kitex/client"etcd "github.com/kitex-contrib/registry-etcd""log""time"
)func main() {//etcd.NewEtcdResolver:创建一个 ETCD 解析器实例,用于从 ETCD 服务注册中心获取服务实例的地址。//参数 []string{"127.0.0.1:2379"} 指定了 ETCD 服务的地址。r, err := etcd.NewEtcdResolver([]string{"127.0.0.1:2379"})if err != nil {log.Fatal(err)}//echo.MustNewClient:创建一个服务客户端实例。//"Hello" 是服务名称,与服务端在 ETCD 中注册的名称一致。//client.WithResolver(r):指定使用 ETCD 解析器 r 来动态发现服务实例。这意味着客户端会从 ETCD 中获取服务实例的地址,而不是直接指定服务地址。client := echo.MustNewClient("Hello", client.WithResolver(r))//创建一个带有超时时间的上下文,超时时间为 3 秒。for {ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)//调用服务端的 Echo 方法,传递一个请求对象,其中 Message 字段为 "hello"。resp, err := client.Echo(ctx, &api.Request{Message: "hello"})cancel() //调用 cancel() 释放上下文资源。if err != nil {log.Fatal(err)}log.Println(resp)time.Sleep(time.Second)}
}

来捋顺一下步骤:

实现一个 Kitex 客户端程序,通过 ETCD 注册中心动态发现服务,并调用名为 Hello 的服务的 Echo 方法:

创建 ETCD 解析器实例,用于从 ETCD 注册中心获取服务实例的地址。然后创建服务客户端实例,指定使用 ETCD 解析器。并且在一个无限循环中,每隔 1 秒调用一次服务的 Echo 方法。打印服务端返回的响应。

这种设计适用于微服务架构,其中服务实例可能动态变化,通过 ETCD 注册中心可以实现服务发现和负载均衡。

通过命令 go run .\handler.go来启动服务端,会将我们的服务注册到etcd里面去。

在这里插入图片描述
然后运行client,会看到如下的消息。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/894845.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数学】矩阵、向量(内含矩阵乘法C++)

目录 一、前置知识:向量(一列或一行的矩阵)、矩阵1. 行向量2. 列向量3. 向量其余基本概念4. 矩阵基本概念5. 关于它们的细节 二、运算1. 转置(1)定义(2)性质 2. 矩阵(向量&#xff0…

浅尝yolo11全程记录1-准备环境+官网模型推理(个人备份)

准备工作(虚拟环境、导入项目) 安装Anaconda 主要是为了创建和管理虚拟环境,在pycharm里按照项目里的requirments.txt安装依赖的时候,使用虚拟环境会好很多(我记得不用Anaconda也可以直接在pycharm的terminal里头创建…

5.攻防世界 fileinclude

进入题目页面如下 提示flag在flag.php ctrlu&#xff0c;查看源码 给出了一段PHP代码&#xff0c;进行代码审计 <?php // 检查是否开启了错误显示功能 if( !ini_get(display_errors) ) {// 如果没有开启&#xff0c;则将错误显示功能设置为开启状态ini_set(display_error…

红包雨项目前端部分

创建项目 pnpm i -g vue/cli vue create red_pakage pnpm i sass sass-locader -D pnpm i --save normalize.css pnpm i --save-dev postcss-px-to-viewportpnpm i vantlatest-v2 -S pnpm i babel-plugin-import -Dhttps://vant.pro/vant/v2/#/zh-CN/<van-button click&…

蓝桥杯嵌入式备赛(三)—— LED +按键 + LCD

目录 一、LED1、原理图介绍2、程序代码 二、按键1、原理图介绍2、程序代码 三、LCD1、原理图介绍2、程序代码 一、LED 1、原理图介绍 如果所示&#xff0c;STM32G431RBT6中有八个LED&#xff0c;由八个GPIO控制&#xff0c;分别为PC8-15&#xff0c;当输出为低电平时点亮。其中…

[Java基础]函数式编程

Lambda函数 JDK8新增的语法形式, 使用Lambda函数替代某些匿名内部类对象&#xff0c;从而让程序代码更简洁&#xff0c;可读性更好。 基本使用 lambda表达式只能简化函数式接口的匿名内部类写法 // 1.定义抽象类 abstract class Animal {public abstract void crt(); }publi…

Vim 多窗口编辑及文件对比

水平分割 :split 默认使用水平分割的方式。 :split :sp 垂直分割 :vsplit :vs 带文件的分割 :split 文件名 :sp 文件名 在光标所在的窗口&#xff0c;输入分割窗口命令就会对那个窗口进行分割。 切换窗口 Ctrlw 切换正在编辑的窗口 快速分割窗口 Ctrlwn 快速分割当前…

二级C语言题解:十进制转其他进制、非素数求和、重复数统计

目录 一、程序填空&#x1f4dd; --- 十进制转其他进制 题目&#x1f4c3; 分析&#x1f9d0; 二、程序修改&#x1f6e0;️ --- 非素数求和 题目&#x1f4c3; 分析&#x1f9d0; 三、程序设计&#x1f4bb; --- 重复数统计 题目&#x1f4c3; 分析&#x1f9d0; 前言…

使用服务器部署DeepSeek-R1模型【详细版】

文章目录 引言deepseek-r1IDE或者终端工具算力平台体验deepseek-r1模型总结 引言 在现代的机器学习和深度学习应用中&#xff0c;模型部署和服务化是每个开发者面临的重要任务。无论是用于智能推荐、自然语言处理还是图像识别&#xff0c;如何高效、稳定地将深度学习模型部署到…

央行发布《贸易金融分布式账本技术要求》,参考架构包括5部分

《银行科技研究社》(作者 木子剑):2024年12月11日,中国人民银行发布金融行业标准《贸易金融分布式账本技术要求》(JR/T 0308-2024)(以下简称“《要求》”),当日实施。据悉,该文件的起草单位包括6大行和多家股份制银行等。 《要求》规定了分布式账本技术在贸易金融领域…

Python aiortc API

本研究的主要目的是基于Python aiortc api实现抓取本地设备媒体流&#xff08;摄像机、麦克风&#xff09;并与Web端实现P2P通话。本文章仅仅描述实现思路&#xff0c;索要源码请私信我。 1 demo-server解耦 1.1 原始代码解析 1.1.1 http服务器端 import argparse import …

记录 | WPF基础学习Style局部和全局调用

目录 前言一、Style1.1 例子1.2 为样式起名字1.3 BasedOn 继承上一个样式 二、外部StyleStep1 创建资源字典BaseButtonStyle.xamlStep2 在资源字典中写入StyleStep3 App.xaml中写引用路径【全局】Step4 调用三、代码提供四、x:Key和x:Name区别 更新时间 前言 参考文章&#xff…

吴恩达深度学习——卷积神经网络实例分析

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 LeNet-5AlexNetVGG-16ResNets残差块 1*1卷积 LeNet-5 输入层&#xff1a;输入为一张尺寸是 32 32 1 32321 32321的图像&#xff0c;其中 32 32 3232 3232是图像的长和宽&…

【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据

一、下载z-paing插件 注意下载下载量最多的这个 进入Hbuilder以后点击“确定” 插件的官方文档地址&#xff1a; https://z-paging.zxlee.cn 二、z-paging插件的使用 在文档中向下滑动&#xff0c;会有使用方法。 使用z-paging标签将所有的内容包起来 配置标签中的属性 在s…

【B站保姆级视频教程:Jetson配置YOLOv11环境(七)Ultralytics YOLOv11配置】

Jetson配置YOLOv11环境&#xff08;7&#xff09;Ultralytics YOLOv11环境配置 文章目录 1. 下载YOLOv11 github项目2. 安装ultralytics包3. 验证ultralytics安装3.1 下载yolo11n.pt权重文件3.2 推理 1. 下载YOLOv11 github项目 创建一个目录&#xff0c;用于存放YOLOv11的项目…

第二天:系统从BIOS/UEFI到GRUB/bootloader的启动过程

目录 **一、BIOS/UEFI初始化阶段****二、引导加载程序&#xff08;GRUB&#xff09;的启动过程****1. BIOS模式下的GRUB分阶段加载****2. UEFI模式下的GRUB加载** **三、操作系统内核加载与初始化****四、关键组件与配置文件****五、故障排查与恢复****总结**常见问题如何在UEF…

【容器技术01】使用 busybox 构建 Mini Linux FS

使用 busybox 构建 Mini Linux FS 构建目标 在 Linux 文件系统下构建一个 Mini 的文件系统&#xff0c;构建目标如下&#xff1a; minilinux ├── bin │ ├── ls │ ├── top │ ├── ps │ ├── sh │ └── … ├── dev ├── etc │ ├── g…

【C语言系列】深入理解指针(5)

深入理解指针&#xff08;5&#xff09; 一、sizeof和strlen的对比1.1sizeof1.2strlen1.3sizeof和strlen的对比 二、数组和指针笔试题解析2.1 一维数组2.2 字符数组2.2.1代码1&#xff1a;2.2.2代码2&#xff1a;2.2.3代码3&#xff1a;2.2.4代码4&#xff1a;2.2.5代码5&#…

【蓝桥杯嵌入式】2_LED

1、电路图 74HC573是八位锁存器&#xff0c;当控制端LE脚为高电平时&#xff0c;芯片“导通”&#xff0c;LE为低电平时芯片“截止”即将输出状态“锁存”&#xff0c;led此时不会改变状态&#xff0c;所以可通过led对应的八个引脚的电平来控制led的状态&#xff0c;原理图分析…

Diskgenius系统迁移之后无法使用USB启动

前言 本文用于记录系统迁移中遇到的问题及解决方法&#xff0c;如有不对请指出&#xff0c;谢谢&#xff01; 现象 使用DiskGenius进行系统迁移后&#xff0c;使用USB启动失败&#xff0c;反复在品牌logo和黑屏之间切换&#xff0c;期间还会在左上角显示”reset system“报错…