【字节青训营-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.rhkb.cn/news/13703.html

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

相关文章

设计模式Python版 享元模式

文章目录 前言一、享元模式二、享元模式示例 前言 GOF设计模式分三大类: 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式:关注类和对象之间的组合&…

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

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

IDEA 中集成 Maven,配置环境、创建以及导入项目

目录 在 IntelliJ IDEA 中集成 Maven 并配置环境 1. 打开 IDEA 设置 2. 定位 Maven 配置选项 3. 配置 Maven 路径 4. 应用配置 创建 Maven 项目 1. 新建项目 2. 选择项目类型 3. 配置项目信息 4. 确认 Maven 设置 5. 完成项目创建 导入 Maven 项目 1. 打开导入窗口…

javaEE-6.网络原理-http

目录 什么是http? http的工作原理: 抓包工具 fiddler的使用 HTTP请求数据: 1.首行:​编辑 2.请求头(header) 3.空行: 4.正文(body) HTTP响应数据 1.首行:​编辑 2.响应头 3.空行: 4.响应正文…

链式结构二叉树(递归暴力美学)

文章目录 1. 链式结构二叉树1.1 二叉树创建 2. 前中后序遍历2.1 遍历规则2.2 代码实现图文理解 3. 结点个数以及高度等二叉树结点个数正确做法: 4. 层序遍历5. 判断是否完全二叉树 1. 链式结构二叉树 完成了顺序结构二叉树的代码实现,可以知道其底层结构…

复制粘贴小工具——Ditto

在日常工作中,复制粘贴是常见的操作,但Windows系统自带的剪贴板功能较为有限,只能保存最近一次的复制记录,这对于需要频繁复制粘贴的用户来说不太方便。今天,我们介绍一款开源、免费且功能强大的剪贴板增强工具——Dit…

【Unity3D小功能】Unity3D中实现超炫按钮悬停效果

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群:398291828小红书小破站 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 先来看一下效果图: 感觉这种效果…

优化深度神经网络

训练集、开发集(验证集)、测试集 偏差与方差 正则化 L2正则 Dropout 随机丢弃部分神经元输入,经常用于计算机视觉的神经网络内,因为通常没有足够的训练数据,很容易出现过拟合的问题 数据增强 训练集规一化 可以使其图像更均匀,…

从java角度对比nodejs、fastapi,同步和异步区别

我之前一直用java语言编程,最近一年用python fastapi和nodejs nestjs开发了一些项目,站在java程序员的角度谈谈异步编程和同步编程的区别,主要在两方面 处理请求,java常用的tomcat是多线程处理请求并执行代码,同步阻塞…

《图解设计模式》笔记(五)一致性

十一、Composite模式:容器与内容的一致性 像文件夹与文件一样,文件夹中可以放子文件夹与文件,再比如容器中可以放更小的容器和具体内容。 Composite模式:使容器与内容具有一致性,创造出递归结构。 Composite&#x…

爬虫学习笔记之Robots协议相关整理

定义 Robots协议也称作爬虫协议、机器人协议,全名为网络爬虫排除标准,用来告诉爬虫和搜索引擎哪些页面可以爬取、哪些不可以。它通常是一个叫做robots.txt的文本文件,一般放在网站的根目录下。 robots.txt文件的样例 对有所爬虫均生效&#…

电脑可以自己换显卡吗?怎么操作

电脑是否可以自己换显卡主要取决于电脑的类型(台式机或笔记本)以及电脑的硬件配置。以下是对这一问题的详细解答及操作步骤: 一、判断电脑是否支持更换显卡 台式机:大多数台式电脑都支持更换显卡。只要主板上有PCIe插槽&#xff…

【玩转 Postman 接口测试与开发2_014】第11章:测试现成的 API 接口(下)——自动化接口测试脚本实战演练 + 测试集合共享

《API Testing and Development with Postman》最新第二版封面 文章目录 3 接口自动化测试实战3.1 测试环境的改造3.2 对列表查询接口的测试3.3 对查询单个实例的测试3.4 对新增接口的测试3.5 对修改接口的测试3.6 对删除接口的测试 4 测试集合的共享操作4.1 分享 Postman 集合…

华为支付-免密支付接入免密代扣说明

免密代扣包括支付并签约以及签约代扣场景。 开发者接入免密支付前需先申请开通签约代扣产品(即申请配置免密代扣模板及协议模板ID)。 华为支付以模板维度管理每一个代扣扣费服务,主要组成要素如下: 接入免密支付需注意&#x…

Redis - 全局ID生成器 RedisIdWorker

文章目录 Redis - 全局ID生成器 RedisIdWorker一、引言二、实现原理三、代码实现代码说明 四、使用示例示例说明 五、总结 Redis - 全局ID生成器 RedisIdWorker 一、引言 在分布式系统中,生成全局唯一ID是一个常见的需求。传统的自增ID生成方式在分布式环境下容易出…

YOLOv11实时目标检测 | 摄像头视频图片文件检测

在上篇文章中YOLO11环境部署 || 从检测到训练https://blog.csdn.net/2301_79442295/article/details/145414103#comments_36164492,我们详细探讨了YOLO11的部署以及推理训练,但是评论区的观众老爷就说了:“博主博主,你这个只能推理…

用Python获取股票数据并实现未来收盘价的预测

获取数据 先用下面这段代码获取上证指数的历史数据,得到的csv文件数据,为后面训练模型用的 import akshare as ak import pandas as pd# 获取上证指数历史数据 df ak.stock_zh_index_daily(symbol"sh000001")# 将数据保存到本地CSV文件 df.…

RK3576——USB3.2 OTG无法识别到USB设备

问题:使用硬盘接入到OTG接口无热插拔信息,接入DP显示屏无法正常识别到显示设备,但是能通过RKDdevTool工具烧录系统。 问题分析:由于热插拔功能实现是靠HUSB311芯片完成的,因此需要先确保HUSB311芯片驱动正常工作。 1. …

RabbitMQ深度探索:前置知识

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

maven如何不把依赖的jar打包到同一个jar?

spring boot项目打jar包部署: 经过以下步骤, 最终会形成maven依赖的多个jar(包括lib下添加的)、 我们编写的程序代码打成一个jar,将程序jar与 依赖jar分开,便于管理: success: 最终…