String name = new String(gbkBytes, Charset.forName("GBK"));
// 再交给 protobuf 序列化 内部会按 UTF-8 写出

老系统把 GBK 编码的商户名直接赋给 string 字段,新服务一收就报 grpc: error while marshaling: string field contains invalid UTF-8,整个批量接口失败。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:proto3 的 string 强制要求 UTF-8,序列化时会做一次校验,不合法就拒绝发送。bytes 字段不做这个检查,但接收端如果按 string 读还是会崩。

「Protobuf 字符串编码」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。同一份配置存在多处的,先确认改的是被加载的那一份。

新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。

处理上按这个顺序:在写入前统一转成 UTF-8 不要直接拿数据库里的 GBK 字节;确实要传原始字节就改用 bytes 字段 由业务层自己解码;检查数据库连接串的 characterEncoding 是否被改过;用一条中文商户名从老库读到新服务 走完整链路验证。

确认没问题再收工,中文商户名能正常发送和接收 日志里不再出现 invalid UTF-8。

作者 9823189