知其然,知其所以然
gRPC 2026-10-12

TLS 与 mTLS:证书校验失败时客户端看到的错误

实测 gRPC 的 TLS/mTLS:证书各种问题时客户端看到的 Unavailable 错误文字;mTLS 缺证书、错 CA 的差别;服务端从 AuthInfo 读客户端身份;证书轮换只对新连接生效;握手的耗时。

gRPC TLS mTLS 证书 x509 证书轮换 ALPN 握手 Go 真实验证 动画演示
gRPC 2026-10-12

认证:per-RPC credentials 与 token 刷新

实测 gRPC 的 per-RPC credentials:声明需要加密时明文连接会被拒绝,声明不需要时令牌在线上是明文;每个请求调用一次、HPACK 让重复令牌只剩几个字节;令牌过期前不提前刷新会被拒 9.2%;并发刷新不加锁会取 50 次;错误码的映射;连接级与单次凭证是叠加。

gRPC 认证 PerRPCCredentials token 令牌刷新 惊群 RequireTransportSecurity Go 真实验证 动画演示
gRPC 2026-10-12

protobuf 的向后兼容:服务升级时新旧客户端互通

实测 protobuf 的兼容性:加字段安全且经过旧服务端不丢;改名二进制兼容但 JSON 破坏;改编号悄悄丢值;int32 改 sint32 值错位;复用编号不报错但含义错位;枚举新值保留数值;标量改 repeated 单向兼容。

gRPC protobuf 向后兼容 字段编号 未知字段 枚举 wire type Go 真实验证 动画演示
gRPC 2026-10-12

proto3 默认值与 optional 在 RPC 接口里的坑

实测 proto3 默认值与存在性:默认值不上线、服务端分不清没设置和设为 0;optional 多 2 字节记录有无;包装类型的做法;部分更新用 Merge 清不了零值;子消息和 nil getter;protojson 默认不输出零值、int64 是字符串。

gRPC protobuf proto3 默认值 optional Has FieldMask protojson Go 真实验证 动画演示
gRPC 2026-10-12

gRPC-Gateway:把 gRPC 暴露成 REST 的转换成本

实测 grpc-gateway v2.31.0:路径与查询参数映射、gRPC 状态码到 HTTP 状态码的多对一映射、JSON 体积是 protobuf 的 1.3 到 3.3 倍、经 gateway 的耗时是直连 gRPC 的 2 到 5 倍、自定义头默认不转发、客户端断开会取消后端、服务端流变成 JSON 行。

gRPC grpc-gateway REST JSON 转码 状态码映射 Go 真实验证 动画演示
gRPC 2026-10-12

gRPC-Web:浏览器为什么需要代理

用本机 Chrome 实测:浏览器 fetch 直接调原生 gRPC 能拿到响应体,但读不到 grpc-status(HTTP/2 trailers 不暴露),跨域还因预检失败;grpc-web 把 trailers 变成响应体最后一帧(标志位 128),服务端流可以边收边读。

gRPC gRPC-Web 浏览器 fetch trailers CORS Chrome 真实验证 动画演示
gRPC 2026-10-12

Go 的 grpc 服务器:每个请求一个 goroutine 的代价

实测 grpc-go 服务端每个在途调用:1 个 goroutine、约 11 KiB(堆约 3 KiB + 栈约 8 KiB);NumStreamWorkers 在 worker 忙时仍新开 goroutine,不能限流,信号量可以;不看 ctx 的 handler 在客户端取消后仍占着 goroutine。

gRPC goroutine 内存 并发 NumStreamWorkers ctx 取消 Go 真实验证 动画演示
gRPC 2026-10-12

序列化成本:大消息的内存拷贝与 buffer 复用

实测 grpc-go 序列化与内存:Marshal/Unmarshal 分配约等于 payload;整个 echo RPC 大消息稳定分配 payload 的 3~4 倍;小消息每次约 11 KiB 固定开销;1 MiB 中文 string 的反序列化比 bytes 慢约 12 倍;缓冲池的开关在这个版本不导出。

gRPC protobuf 序列化 内存分配 UTF-8 bytes 大消息 Go 真实验证 动画演示
gRPC 2026-10-12

超时的叠加:客户端、网关、服务端各设一个会怎样

实测 gRPC 调用链上的超时叠加:各层取最小;内层比外层剩余时间还长的超时不起作用;deadline 以剩余时间的形式(grpc-timeout 头)每一跳递减;A 重试 B 3 次会吃掉外层的预算;转发调用不传 ctx 会让下游白做工作。

gRPC 超时 deadline 调用链 grpc-timeout 重试预算 Go 真实验证 动画演示
gRPC 2026-10-12

优雅停机:GracefulStop 与 Stop 的区别

实测 grpc-go 的优雅停机:Stop 立即让在途调用失败,GracefulStop 等到做完;一个不结束的流能让 GracefulStop 永远等下去;负载下滚动重启 Stop 失败 8 个而 GracefulStop 0 个;Stop 默认不等 handler 返回,WaitForHandlers 才等。

gRPC 优雅停机 GracefulStop Stop 滚动重启 WaitForHandlers health Go 真实验证 动画演示
gRPC 2026-10-12

流的泄漏:忘记关闭流时服务端会怎样

实测 gRPC 流泄漏:没读完也没取消的流在服务端一直存在,GC 回收不了;泄漏的流占满 MaxConcurrentStreams 会拖死同一连接上的其它调用;CloseSend 不释放服务端流,cancel 或读到 EOF 才算;客户端流必须 CloseAndRecv;泄漏的流让连接永远不空闲。

gRPC 流 泄漏 取消 CloseSend MaxConcurrentStreams MaxConnectionIdle Go 真实验证 动画演示
gRPC 2026-10-12

压测:单连接与多连接的吞吐曲线

本机实测 gRPC 的吞吐曲线:小消息从 1 条连接增加到 4 条吞吐增加约三成,之后到顶;64 KiB 消息 1 条连接就有约 1369 MiB/秒;并发调用者从 1 个到 256 个吞吐涨十倍、p50 延迟从 79 µs 涨到 2090 µs;无并发时流式比 Unary 快约 30%。

gRPC 压测 吞吐 连接数 并发 延迟 Go 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号