grpc 是默认起点但非万能,http/1.1+json 更适合中小团队;选型关键在于排障效率而非技术先进性,需权衡调试成本、团队能力与可观测性需求。

Go 微服务间通信协议选型,核心不是“哪个最先进”,而是“哪个在你的部署环境、团队能力、可观测性需求下出问题时最容易定位和修复”。gRPC 是默认起点,但别盲目上;HTTP/1.1 + JSON 仍是多数中小团队最稳的选择。
什么时候该用 gRPC(而不是 HTTP/JSON)
你明确需要以下至少一项:强类型服务契约、服务端流式响应(如实时日志推送)、客户端流式请求(如大文件分块上传)、或跨语言调用且希望共享 .proto 定义。gRPC 默认走 HTTP/2,天然支持多路复用和头部压缩,但代价是调试困难——curl 看不到请求体,Wireshark 抓包需解密 HTTP/2,错误信息常是模糊的 rpc error: code = Unknown desc = ...。
- 必须用
protoc生成代码,每次接口变更都要同步更新所有语言客户端,CI 流程变重 - 网关层(如 Envoy、Nginx)需显式配置 HTTP/2 支持,Kubernetes Ingress 默认不透传 gRPC 流量,容易卡在 502
- 若服务只对内且全用 Go,可考虑
gRPC-Go的WithInsecure()开发模式,但生产务必配 TLS 和 mTLS
为什么 HTTP/1.1 + JSON 在 Go 微服务里依然靠谱
因为 net/http 足够稳定,encoding/json 序列化开销可控,日志、监控、链路追踪(如 OpenTelemetry)生态成熟。你用 http.Client 发请求,用 httputil.DumpRequestOut 就能完整看到原始字节,错误返回直接是 400 Bad Request + 明确 JSON 错误字段,运维同学不用学新工具。
- 避免过度设计:如果服务 QPS 100ms、无流式场景,gRPC 带来的性能收益远低于调试成本
- 路径和参数语义清晰:
POST /v1/orders比OrderService/CreateOrder更易被 Prometheus、Grafana 理解 - 注意
json.Unmarshal的零值陷阱:结构体字段没加omitempty且值为零时,会序列化进 JSON;反序列化时若字段不存在,默认赋零值而非跳过——这可能导致业务逻辑误判
HTTP/2 自定义协议(非 gRPC)是否值得尝试
不推荐。Go 的 net/http 对 HTTP/2 的 Server Push、自定义帧等高级特性支持有限,且缺乏标准序列化约定。你得自己定义消息头、编解码规则、错误码映射,最终既没 gRPC 的工具链,又丢掉了 HTTP/1.1 的通用性。真有低延迟诉求,优先优化序列化(如改用 msgpack 或 cbor)和连接复用(http.Transport.MaxIdleConnsPerHost 调高),而不是换协议栈。
- HTTP/2 的连接复用本身就能显著降低建连开销,但前提是客户端复用
*http.Client实例,而非每次 new 一个 - 若强行用 HTTP/2 自定义二进制 payload,Wireshark 无法解析,
tcpdump抓到的全是乱码,线上排障等于蒙眼拆弹
协议选型真正的分水岭不在技术参数表里,而在你的错误日志里——当 503 Service Unavailable 出现时,你是想立刻看到 JSON 错误详情,还是愿意花半小时配好 grpcurl 和 TLS 证书再试一次?
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











