GitHub user Bughue edited a discussion: Seata multi-version protocol control design and discuss
## 1 背景 - 问题一:seata的通信协议报文结构在0.7.1版本发生了较重大的变化,但并没有对之前的协议做兼容处理,导致旧版本服务端的用户若想升级时只能同时升级服务端和客户端,也就是要么忍受一段时间的不可通信,要么就停机升级了。 - 问题二:协议扩展性有问题, 扩充字段或类型后跟前面协议不兼容。(扩展方式不统一、适配逻辑就会分散在各层级里面,造成混乱,无法管理) - 过往讨论:https://github.com/seata/seata/pull/4569/files ## 2 新旧版本协议结构分析 [分布式事务SEATA 新旧通信协议结构分析](https://zhuanlan.zhihu.com/p/634199908) ## 3 改造思路概述 当前的第一个目标,应该是新版本的seata-server可以和旧版本的client通信(如果要做新版本的client能和旧版本的server通信道理也类似),我认为我们需要做的是以下几件事 - 新版本server识别旧版本协议 - 新版本server解析旧版本协议 - 新版本server将对方标记为旧版本应用,绑定到channel - 新版本server向对方发起旧版本的通信报文 第二个目标,是协议扩展性优化 - 跨版本的适配统一到codec里面进行(codec按版本号分离) - 服务器按照最新版本的message处理业务逻辑 ## 4 协议结构兼容设计 #### 4.1 协议结构兼容设计 - 新版本server识别旧版本协议 - <img width="1179" alt="image" src="https://github.com/seata/seata/assets/3788653/789f6d07-153a-43eb-8abf-1023c9130f04"> - 参考上图,以及[分布式事务SEATA 新旧通信协议结构分析](https://zhuanlan.zhihu.com/p/634199908) 可以看出判断第三个byte是能判断协议版本的,因为0.6.1以下版本的这个byte都和现在的1不一样,实际上到达1024甚至更多都不冲突 - 新版本server解析旧版本协议 - 识别到是旧版本后,按照旧版本的逻辑解释即可。关键的是缺失的字段要给一个能兼容好老版本的默认值 - 新版本server将对方标记为旧版本应用,绑定到channel - 在TM/RM注册到TC的时候,TC会记录channel,在这个时候要进行协议版本的保存,方便向他们发出消息 - 新版本server向对方发起旧版本的通信报文 - 在判断到对方TM/RM是旧版本client时,用旧协议的方式去encode/decode #### 4.2 扩展性设计优化 - codec按版本分包,明确的把各版本分开 - 服务端解析message对象时(接收):按最新版本codec接收(decode适配) - 服务端创建message对象时(发送):发送前按版本选择codec(encode适配) - 识别版本(从头部解析) ``` boolean isV0 = false; in.markReaderIndex(); byte b0 = in.readByte(); byte b1 = in.readByte(); // v1/v2/v3 : b2 = version // v0 : 1st byte in FLAG(2byte:0x10/0x20/0x40/0x80) byte b2 = in.readByte(); if (ProtocolConstants.MAGIC_CODE_BYTES[0] == b0 && ProtocolConstants.MAGIC_CODE_BYTES[1] == b1 && 0 == b2) { isV0 = true; } ``` ## 5 改造前后流程对比(服务端接收) - 流程图  - 说明 - 在serialize和rpc包里都要按版本号新建目录,里面包含各版本的解析 - 版本号在流程中必须清晰,我们传递的对象又是rpcMessage,所以是建议在里面加一个字段来中途保存版本号 - 对于message的serialize:v1和后续的v2、v3等等都会保持一致,只有v0有差异 ## 6 改造前后流程对比(服务端发送) - 流程图  - 说明 - 改造点和接收匹配 - 对于message的serialize:要在启动的时候把各版本codec加入工厂(这部分流程图未体现),然后在发送之前按版本选择codec ## 7 PR - https://github.com/apache/incubator-seata/pull/6226 GitHub link: https://github.com/apache/incubator-seata/discussions/5628 ---- This is an automatically sent email for dev@seata.apache.org. To unsubscribe, please send an email to: dev-unsubscr...@seata.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@seata.apache.org For additional commands, e-mail: dev-h...@seata.apache.org