json 转pb 问题定位

背景

线上服务升级一天后,大数据过来告诉我说昨天一天的数据大批下滑。

分析

一脸懵逼。昨天升级的服务我是分步升级的,之前的一周我已经升级了1/10的服务,验证业务的稳定,运行一周后,线上无反馈,所以昨天开始批量升级。

我只能把逻辑重新看了一遍,最后锁定再pb新增加了字段如下

1
2
3
4
5
6
7
8
9
10
11
12
message UserBase
{
optional int32 userid = 1; // 用户ID
optional int32 ip = 2; // IP
optional int32 groupid = 3; // 大厅组ID
optional int32 recommenderid = 4; // 推广(员)ID
optional int32 channel = 5; // 渠道号
optional int32 usertype = 6; // 用户类型( 0:普通用户 1:会员用户)
optional int32 groupopt = 7; // group options
optional string addinfo = 8; // 玩家自定义数据 -- 新增
optional string idcard = 9; // 身份证号 -- 新增
}

按理说pb中新增加字段,没修改序号是没什么影响的,但为什么偏偏出问题了呢?
继续分析,原来是 json->pb 出现的问题。

问题

A服务将pb内容序列化json写入redis

1
2
3
4
5
6
7
8
9
//	  bPrimitie false:不输出默认参数, true :输出所有参数
BOOL PB_Msg2Json(const ::google::protobuf::Message& msg, std::string& strJson, bool bMultiLine,bool bPrimitie)
{
google::protobuf::util::JsonPrintOptions jpo;
jpo.add_whitespace = bMultiLine;//multiline 多行显示
jpo.always_print_primitive_fields = bPrimitie; //保留字段是否默认输出

return google::protobuf::util::MessageToJsonString(msg, &strJson, jpo).ok();
}

B服务从redis读取json在序列化为pb

1
2
3
4
5
6
BOOL PB_Json2Msg(const std::string& strJson, ::google::protobuf::Message& msg)
{
google::protobuf::util::JsonParseOptions jpo;

return google::protobuf::util::JsonStringToMessage(strJson, &msg, jpo).ok();
}

pb新增加了字段,A服务升级,导致redis中的json多了两个字段,这时B服务未升级将json序列为老pb失败。

原因在于PB_Json2Msg 默认的 options 设置问题

1
2
3
4
5
6
7
BOOL PB_Json2Msg(const std::string& strJson, ::google::protobuf::Message& msg)
{
google::protobuf::util::JsonParseOptions jpo;
jpo.ignore_unknown_fields = true; // 过滤掉json和pb不相同的字段

return google::protobuf::util::JsonStringToMessage(strJson, &msg, jpo).ok();
}