应使用 Protocol Buffers 替代 JSON 作为序列化格式,因其二进制、强类型、字段编号传输,体积减少60%–80%,gRPC原生支持;配合grpc-gateway兼顾REST兼容性。
Go 微服务间 HTTP 或 gRPC 通信时,默认用 json.Marshal 会导致 CPU 占用高、体积大、解析慢。Protocol Buffers(.proto 定义 + protoc-gen-go 生成代码)是更优选择,尤其在 gRPC 场景下原生支持。
json 是文本格式,无 schema 校验,字段名重复传输,不压缩;protobuf 是二进制、有强类型定义、字段用 tag 编号而非名称,体积通常减少 60%–80%protobuf,若用 http + json,可改用 grpc-gateway 暴露 REST 接口,后端仍走 protobuf 编解码go_package 和 option go_package 路径,并在 CI 中校验生成代码一致性service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse);
}
message GetUserR
equest {
int64 user_id = 1;
}
message GetUserResponse {
User user = 1;
bool found = 2;
}
当服务需要批量获取或实时推送数据(如日志流、监控指标、订单状态变更),反复调用 Unary RPC 会产生显著延迟和连接开销。gRPC 支持 server-streaming、client-streaming 和 bidi-streaming,能复用连接、减少 handshake 开销。
GetOrderStatus(ctx, &req) 100 次;改用 StreamOrderStatus(ctx, &StreamReq{Ids: ids})
context.WithTimeout 应覆盖整个流生命周期,而非单次 Recv()
Send() 前做重载计算;否则会阻塞流,影响其他并发流高频读取的只读数据(如配置项、地区列表、汇率)不应每次通过 HTTP/gRPC 调用远程服务获取,应通过本地缓存降低 RT 和下游压力。
github.com/patrickmn/go-cache 或 github.com/bluele/gcache 实现带 TTL 的内存缓存,避免自己手写锁和过期逻辑"region_list_v202505"),便于发布时强制刷新WATCH/MULTI 或基于事件驱动的缓存失效(如监听 Kafka topic config-updated)常见反模式:A 服务把原始数据塞进 map[string]interface{},B 服务再用 json.Unmarshal 解析并映射到结构体——这绕过了编译期类型检查,且无法利用 protobuf 的零拷贝优化。
立即学习“go语言免费学习笔记(深入)”;
api/ 或 proto/ 仓库中,由 CI 自动生成 Go/Java/TS 代码,禁止手动维护 DTOjson.RawMessage 透传;若需兼容旧版,应由网关层完成协议转换,业务服务只对接标准 proto messageoptional(proto3),弃用字段加 deprecated = true
*.pb.go 直接提交,导致 diff 失控;正确做法是只提交 .proto,CI 自动检查并生成,失败即阻断发布。