【字节青训营-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…

TCP/IP 邮件

TCP/IP 邮件 引言 在互联网技术飞速发展的今天,电子邮件(Email)已成为人们日常工作和生活中不可或缺的通信工具。TCP/IP协议作为互联网通信的基础,为电子邮件的传输提供了强大的技术支持。本文将详细介绍TCP/IP在电子邮件传输过程中的作用,以及相关的协议和实现方式。 …

离线安装Appium Server

1、问题概述? 安装Appium通常有两种方式: 第一种:下载exe安装包,这种是Appium Server GUI安装方式,缺点是通过命令启动不方便。 第二种:通过cmd安装appium server,可以通过命令方式启动,比较方便。 问题:在没有外网的情况下,无法通过命令在cmd中安装appium server…

设计模式六大原则和单例模式

设计模式 目的 实现可重用解决方案,构筑易维护、可扩展的软件系统。 六大原则 单一职责: 类的职责单一,一个方法做一件事。 开闭原则: 拓展开放,修改关闭。 里氏替换: 父类能出现的地方,子…

浅尝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…

深入浅出 NRM:加速你的 npm 包管理之旅

文章目录 前言一、NRM 是什么&#xff1f;二、为什么需要 NRM&#xff1f;三、NRM 的优势四、NRM 的安装与使用4.1 安装 NRM4.2 查看可用的 npm 源4.3 切换 npm 源4.4 测试 npm 源速度4.5 添加自定义 npm 源4.6 删除 npm 源 五、NRM 的进阶使用六、总结 前言 作为一名 JavaScr…

《C#之集训1-20121019c#基础》

&#xfeff;&#xfeff; C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。它是微软公司研究员Anders Hejlsberg的最新成果。 C#曾经的它在我眼中是很高大上的&#xff0c;一直没有目睹其风采&#xff0c;现在终于揭开了它神秘的面纱&#xf…

红包雨项目前端部分

创建项目 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;当输出为低电平时点亮。其中…

深入剖析 HTML5 新特性:语义化标签和表单控件完全指南

系列文章目录 01-从零开始学 HTML&#xff1a;构建网页的基本框架与技巧 02-HTML常见文本标签解析&#xff1a;从基础到进阶的全面指南 03-HTML从入门到精通&#xff1a;链接与图像标签全解析 04-HTML 列表标签全解析&#xff1a;无序与有序列表的深度应用 05-HTML表格标签全面…

[Java基础]函数式编程

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

Vue通过触发与监听事件进行数据传递: 子组件调用 $emit 方法来将数据传递给父组件。

文章目录 引言I 组件事件事件参数defineEmits 宏声明需要抛出的事件事件校验例子:子组件告诉父组件放大所有博客文章的文字II 【详细说明】 子组件通过触发一个事件,将数据传递给父组件调用内建的 `$emit `方法传入事件名称来触发一个事件子组件通过`this.$emit`来触发一个事…

Vim 多窗口编辑及文件对比

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

“卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法

在与上千学员交流过程中&#xff0c;发现科研、生产和应用多源遥感数据时&#xff0c;能快速上手&#xff0c;发挥数据的时效性&#xff0c;尽快出创新性成果&#xff0c;是目前的学员最迫切的需求。特别是按照“遥感数据获取-处理-分析-计算-制图”全流程的答疑解惑&#xff0…

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

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

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

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

让相机自己决定拍哪儿!——NeRF 三维重建的主动探索之路

我在 NeRF 中折腾自动探索式三维重建的心得 写在前面&#xff1a; 最近我在研究三维重建方向&#xff0c;深切感受到 NeRF (Neural Radiance Fields) 在学术界和工业界都备受瞩目。以往三维重建通常要依赖繁琐的多视图几何管线&#xff08;比如特征匹配、深度估计、网格融合等&…

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

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

管理etcd的存储空间配额

如何管理etcd的存储空间配额 - 防止集群存储耗尽指南 本文基于etcd v3.4官方文档编写 为什么需要空间配额&#xff1f; 在分布式系统中&#xff0c;etcd作为可靠的键值存储&#xff0c;很容易成为系统瓶颈。当遇到以下情况时&#xff1a; 应用程序频繁写入大量数据未及时清理…