当前位置: 首页 > news >正文

【字节青训营-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,会看到如下的消息。

在这里插入图片描述

相关文章:

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

本文目录 一、Kitex概述二、第一个Kitex应用三、IDL四、服务注册与发现 一、Kitex概述 长话短说,就是字节跳动内部的 Golang 微服务 RPC 框架,具有高性能、强可扩展的特点,在字节内部已广泛使用。 如果对微服务性能有要求,又希望…...

给AI用工具的能力——Agent

ReAct框架: Reason Action,推理与行动结合 可以借助思维链,用小样本提示展示给模型一个ReAct框架 推理:针对问题或上一步观察的思考 行动:基于推理,与外部环境的一些交互(调用外部工具&…...

Jupyter Lab的使用

Lab与Notebook的区别: Jupyter Lab和Jupyter notebook有什么区别,这里找到一篇博客不过我没细看, Jupyter Lab和Jupyter Notebook的区别 - codersgl - 博客园 使用起来Lab就是一个更齐全、功能更高级的notebook, 启用滚动输出: 有时候一个…...

【从零开始的LeetCode-算法】922. 按奇偶排序数组 II

给定一个非负整数数组 nums, nums 中一半整数是 奇数 ,一半整数是 偶数 。 对数组进行排序,以便当 nums[i] 为奇数时,i 也是 奇数 ;当 nums[i] 为偶数时, i 也是 偶数 。 你可以返回 任何满足上述条件的…...

RabbitMQ深度探索:前置知识

消息中间件: 消息中间件基于队列模式实现异步 / 同步传输数据作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合 传统的 HTTP 请求存在的缺点: HTTP 请求基于响应的模型,在高并发的情况下,客户端发送大量的请求…...

『 C++ 』中不可重写虚函数的实用案例

文章目录 框架设计:保障核心逻辑稳定避免误操作:防止逻辑混乱确保接口一致:库与API设计 在C编程里,用final关键字修饰、不允许被继承(重写)的虚函数其实很有用。接下来我就结合实际案例,给大家讲…...

Redis - String相关命令

目录 setgetmsetmgetsetnx、setex、psetexincr、incrby、decr、decrby、incrbyfloatappendgetrangesetrangestrlen字符串类型编码方式总结 Redis - String Redis存储的字符串,是直接按二进制方式存储,不会做任何编码转换,存的是什么&#xff…...

pytorch基于FastText实现词嵌入

FastText 是 Facebook AI Research 提出的 改进版 Word2Vec,可以: ✅ 利用 n-grams 处理未登录词 比 Word2Vec 更快、更准确 适用于中文等形态丰富的语言 完整的 PyTorch FastText 代码(基于中文语料),包含&#xff1…...

3D人脸建模:高精度3D人脸扫描设备快速生成真人脸部3D模型

什么是3D人脸建模? 3D人脸建模,即借助特定技术手段,获取人脸三维数据,并构建出能精准呈现人脸形状、纹理等特征的三维模型。这一技术广泛应用于计算机视觉、人机交互、虚拟现实、影视制作等多个领域,为各行业都带来了前所未有的创…...

4.PPT:日月潭景点介绍【18】

目录 NO1、2、3、4​ NO5、6、7、8 ​ ​NO9、10、11、12 ​ 表居中或者水平/垂直居中单元格内容居中或者水平/垂直居中 NO1、2、3、4 新建一个空白演示文稿,命名为“PPT.pptx”(“.pptx”为扩展名)新建幻灯片 开始→版式“PPT_素材.doc…...

冷链监控系统

前后端源码 wx :bright12389 冷链系统需求分析 1. 项目背景 冷链系统用于监控和管理冷链物流过程中的环境参数(如温度、湿度),确保货物在运输、存储过程中的质量安全。系统需支持实时监控、历史数据分析、异常告警等功能。 2.…...

VSCode中代码颜色异常

检查右下角语言模式是否是HTML, 如果不是就点击更改为HTML模式即可...

表格标签的使用

一.表格标签 1.1表格标签的作用 用来显示和展示数据&#xff0c;不是用来布局页面的。 1.2表格的基本语法 <table> //用于定义表格标签 <tr> // table row 用于定义表格中的行&#xff0c;必须嵌套在<table> </table>标签中 <td>单元格内的文…...

llama.cpp GGUF 模型格式

llama.cpp GGUF 模型格式 1. Specification1.1. GGUF Naming Convention (命名规则)1.1.1. Validating Above Naming Convention 1.2. File Structure 2. Standardized key-value pairs2.1. General2.1.1. Required2.1.2. General metadata2.1.3. Source metadata 2.2. LLM2.2.…...

嵌入式硬件篇---HAL库内外部时钟主频锁相环分频器

文章目录 前言第一部分&#xff1a;STM32-HAL库HAL库编程优势1.抽象层2.易于上手3.代码可读性4.跨平台性5.维护和升级6.中间件支持 劣势1.性能2.灵活性3.代码大小4.复杂性 直接寄存器操作编程优势1.性能2.灵活性3.代码大小4.学习深度 劣势1.复杂性2.可读性3.可维护性4.跨平台性…...

【IoCDI】_@Bean的参数传递

目录 1. 不创建参数类型的Bean 2. 创建一个与参数同类型同名的Bean 3. 创建多个与参数同类型&#xff0c;其中一个与参数同名的Bean 4. 创建一个与参数同类型不同名的Bean 5. 创建多个与参数同类型但不同名的Bean 对于Bean修饰的方法&#xff0c;也可能需要从外部传参&…...

[特殊字符] ChatGPT-4与4o大比拼

&#x1f50d; ChatGPT-4与ChatGPT-4o之间有何不同&#xff1f;让我们一探究竟&#xff01; &#x1f680; 性能与速度方面&#xff0c;GPT-4-turbo以其优化设计&#xff0c;提供了更快的响应速度和处理性能&#xff0c;非常适合需要即时反馈的应用场景。相比之下&#xff0c;G…...

【模型】Bi-LSTM模型详解

1. 模型架构与计算过程 Bi-LSTM 由两个LSTM层组成&#xff0c;一个是正向LSTM&#xff08;从前到后处理序列&#xff09;&#xff0c;另一个是反向LSTM&#xff08;从后到前处理序列&#xff09;。每个LSTM单元都可以通过门控机制对序列的长期依赖进行建模。 1. 遗忘门 遗忘…...

directx12 3d开发过程中出现的报错 一

报错&#xff1a;“&”要求左值 “& 要求左值” 这个错误通常是因为你在尝试获取一个临时对象或者右值的地址&#xff0c;而 & 运算符只能用于左值&#xff08;即可以放在赋值语句左边的表达式&#xff0c;代表一个可以被引用的内存位置&#xff09;。 可能出现错…...

Ubuntu 24.04 安装 Poetry:Python 依赖管理的终极指南

Ubuntu 24.04 安装 Poetry&#xff1a;Python 依赖管理的终极指南 1. 更新系统包列表2. 安装 Poetry方法 1&#xff1a;使用官方安装脚本方法 2&#xff1a;使用 Pipx 安装 3. 配置环境变量4. 验证安装5. 配置 Poetry&#xff08;可选&#xff09;设置虚拟环境位置配置镜像源 6…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...