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

Tars请求过程与协议分析

我们通过官网的demo来进行分析,安装demo如下代码所示。

// 1.安装tars相关工具
go install github.com/TarsCloud/TarsGo/tars/tools/tarsgo@latest
go install github.com/TarsCloud/TarsGo/tars/tools/tars2go@latest
// 2.初始化生成代码(完成代码初始化)
tarsgo make App Server Servant GoModuleName
tarsgo make TestApp HelloGo SayHello github.com/Tars/test

基本文件结构如下所示:

CREATED HelloGo/SayHello.tars (171 bytes)// 协议文件
CREATED HelloGo/SayHello_imp.go (620 bytes)
CREATED HelloGo/client/client.go (444 bytes)
CREATED HelloGo/config.conf (967 bytes)
CREATED HelloGo/debugtool/dumpstack.go (412 bytes)
CREATED HelloGo/go.mod (37 bytes)
CREATED HelloGo/main.go (517 bytes)
CREATED HelloGo/makefile (193 bytes)
CREATED HelloGo/scripts/makefile.tars.gomod (4181 bytes)
CREATED HelloGo/start.sh (56 bytes)

协议文件名称:SayHello.tars,Tars才用自研的Tars协议和其他的Rpc框架有所不同,不过Tars也可以兼容proto协议。是从生成的.tars.go开始触发,obj.servant.TarsInvoke为入口开始执行,将参数进行组装传递到Invoke,在doInvoke中执行Rpc调用,通过adapterProxy发送Rpc调用,通过send发包给对应的RPC服务。对应的发送流程图如下。

image.png

func (c *AdapterProxy) Send(req *requestf.RequestPacket) error {
	// 添加发送次数
	c.sendAdd()
	// 发送请求打包
	sbuf, err := c.servantProxy.proto.RequestPack(req)
	if err != nil {
		TLOG.Debug("protocol wrong:", req.IRequestId)
		return err
	}
	// 发送请求
	return c.tarsClient.Send(sbuf)
}

其中Send的实现是一个消息队列。

在收到RPC请求的调用后,执行TCPHandler的invoke方法进行请求处理和解析,解析完再通过链接推回去。

rsp := h.ts.invoke(ctx, pkg) // 处理请求

connSt.conn.Write(rsp) // 结果回写

总的来说就是逐字节读取数据,通过特定算法来进行识别标签类型,并传递给对应的解析器进行解析。

func (b *Reader) readHead() (ty, tag byte, err error) {
	data, err := b.buf.ReadByte()
	if err != nil {
		return
	}
	// 识别标签的算法
	ty = data & 0x0f
	tag = (data & 0xf0) >> 4
	return
}

Tars对于数据的参数位于codec文件夹,其中包含了所有的数据类型的解析。我们以字符串解析为例。

1.获取字符串类型,通过Reader的SkipToNoCheck实现,看是string1还是string4。

2.根据类型去执行对应的解析器,分别是两种部分的情况,string1 为单行字符串,string4为多行字符串。

3.获取要获取的字符串的长度,(bReadU32,逐字节读取)。

4.通过b.Next提取对应的字符串,并返回。

func (b *Reader) ReadString(data *string, tag byte, require bool) error {
	have, ty, err := b.SkipToNoCheck(tag, require)
	if err != nil {
		return err
	}
	if !have {
		return nil
	}
	//此处省略了string4的判断,重点是突出处理方案
	if ty == STRING1 {
		var length uint8
		err = bReadU8(b.buf, &length)
		if err != nil {
			return fmt.Errorf("read string1 tag:%d error:%v", tag, err)
		}
		buff := b.Next(int(length))
		*data = string(buff)
	} else {
		return fmt.Errorf("need string, tag:%d, but type is %s", tag, getTypeStr(int(ty)))
	}
	return nil
}

执行完成ReadForm之后,我们就可以得到一个基本的请求结构信息了,比如调用的是哪个,方法是哪个,超时情况,都一一描述清楚。

image.png
最后补充一下:Tars服务之间的互相调用,RPC通信是基于TCP实现的,非HTTP协议。


http://www.kler.cn/a/5703.html

相关文章:

  • 【git】-2 分支管理
  • 大模型技术与应用:从幻觉到蒸馏,全面解析
  • 计算机组成原理(九):乘法器
  • 2025年第三届“华数杯”国际赛B题解题思路与代码(Matlab版)
  • 本地手集博客id“升级”在线抓取——简陋版——(2024年终总结1.1)
  • 音视频入门基础:MPEG2-PS专题(6)——FFmpeg源码中,获取PS流的视频信息的实现
  • 2023蓝桥杯省模拟赛——滑行
  • 二叉树的前中后序遍历以及求深度、叶子节点和二叉树的重建
  • PE文件格式
  • Linux常用命令之压缩解压命令
  • 华为OD机试题【打折买水果】用 C++ 编码,速通
  • 优思学院 | 质量工程师的职责有哪些?
  • 老鼠迷宫,汉诺塔,八皇后,回溯算法案例
  • Log4j2的RollingFileAppender详解
  • linux系统编程(3)--系统调用
  • 文章八:YOLOv5车牌识别系统的Web应用与API开发
  • Java设计模式(二十一)—— 外观模式
  • 歌德巴赫猜想数学证明
  • Leetcode.2171 拿出最少数目的魔法豆
  • element plus 语言切换组件使用
  • python——面向对象(下)
  • C 中的循环
  • Jenkins使用
  • 【计算机视觉 | 目标检测】DETR风格的目标检测框架解读
  • QT之QCamera
  • Java多态