failed to unmarshal the received message proto问题排查

2 篇文章 0 订阅
本文讲述了作者在工作中遇到的一个由于Proto文件不一致导致的gRPC接口解析错误。早期代码集中管理,后因依赖冲突拆分成多个仓库,导致Proto文件更新不同步。一次更新Proto字段顺序改变,加上服务端未及时发布新版本,造成客户端解析失败。最终解决方案是同步Proto文件并优化流程,避免类似问题。
摘要由CSDN通过智能技术生成

前言

突然发现已经有很久没有登录过csdn了,工作后一直很忙,没有什么时间来写博客,平日学习、踩坑往往都是自己简单记录一下,但实际上经常写博客还是有必要的,一方面可以加深自己的理解,另一方面,也可以不断强化文档书写能力。

背景

由于公司部门较多,语言也各不相同,跨部门协作基本都是通过gRPC协议(proto文件足够通用和认可),因此公司有一个统一API仓库,暂且叫作common。对于各业务方来说,只需要保证自己项目内的proto文件与common仓库自己路径下的proto文件一致即可。

早期主站各业务部门代码都存放在一个仓库内,且同时使用一份go.mod文件,此处暂且叫做main仓库。后来,有一位同学将go.mod中的某个依赖升级,并合入master,而那个依赖的升级引入了一个第三方bug,导致各个业务方都出现了问题,于是,部分组为了避免此类问题的再次发生,以组为单位,将自己组的代码拆到一个独立的小仓中,暂且叫做gateway仓库。

由于早期代码都在一个仓库中,调用同部门其他业务方的gRPC接口就可以不通过common,而是直接在项目内引用业务方的proto,后续拆分小仓时也没有进行依赖梳理,导致每修改一次proto文件,common、main、gateway三个仓库全部需要修改一次,这也为后面的坑埋下伏笔。

按照上述的流程,在开发过程中往往会先更新common中的proto文件,使得协作方可以与你同步开发。但有一个需求,因为开发过程中产品发现其他问题,不能上线,因此服务端代码也没有合入master,此时,common库与main、gateway库proto文件出现不一致。之后又新增了一个字段,但是字段类型都是string,于是线上运行一段时间没有问题。

common:

message Item {
    int64 id = 1;
    // ...
    string from = 33;
}

gateway与main:

message Item {
    int64 id = 1;
    // ...
    string from = 32;
}

某一天,因为新需求需要新增一个int32的字段,在common仓库中更新后,并未发版。过了几个小时后,有业务方更新了common仓库并发版,之后发现接口失败,反馈过来,报错日志如下:

排查

初步确认server端并未发版,该字段并未对外突出,理论上不应该出现解析不出的问题。

后查看protobuf源码,使用的是1.3.2的版本,发现当出现不认识的字段时,会将该部分写入XXX_unrecognized内,并且会继续传递给 client 端,以至于出现新的字段时,只需要client端发版,server端不发版也可以解析新增字段,但因之前造成的顺序不一致,导致新增字段解析失败,报了failed to unmarshal the received message proto的错误。

解决

将问题版本禁止编译,将三个仓库的proto改成一致。后续推进各业务方统一使用common中的proto,下掉main仓库中的proto,渐少维护的仓库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值