生产环境grpc需配置keepalive和错误码透传:必须设grpc.withkeepaliveparams防止空闲断连,用status.errorf返回标准错误码并客户端用status.fromerror解包,否则压测时才暴露“稳不通”问题。

直接用 grpc.Dial 连接、protoc 生成代码、定义好 .proto 文件,就能跑通基础通信——但生产环境卡在连接管理、错误传播、跨服务调试上,不是“能通”,而是“稳不通”。
protoc 生成代码时 go_package 和路径必须严格匹配
很多报错如 cannot find package "xxx" 或 undefined: pb.XXX 都源于此。go_package 不是注释,它决定生成文件的 import 路径和包名,且必须与文件实际存放路径一致。
-
option go_package = "github.com/yourorg/user/v1";→ 生成的user_grpc.pb.go必须放在$GOPATH/src/github.com/yourorg/user/v1/下(或 Go Modules 模式下,该路径需与go.mod的 module 名兼容) - 如果用
paths=source_relative,则protoc命令需从项目根目录执行,否则生成路径错位 - 多个服务共用 proto 时,避免不同
.proto文件写相同go_package,否则编译冲突
grpc.Dial 的连接参数不设超时或 keepalive 就会假死
默认 grpc.Dial 是阻塞同步建连,且无保活机制。服务重启、网络抖动后客户端可能长期 hang 在 conn.Read 或发不出请求,表现为“连接还在但调用无响应”。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 必须加
grpc.WithTimeout(5 * time.Second)控制建连耗时 - 启用 keepalive:
grpc.WithKeepaliveParams(keepalive.ClientParameters{Time: 10 * time.Second}),否则空闲连接被中间设备(如 NAT、LB)静默断开后无法感知 - 禁用 insecure 仅限本地调试;生产必须用
grpc.WithTransportCredentials(credentials.NewTLS(...)) - 不要每次调用都
grpc.Dial;应复用*grpc.ClientConn实例,它是线程安全的
Unary RPC 错误码被吞掉,导致上游无法区分业务失败和网络失败
gRPC 默认把所有 error 都转成 status.Error(codes.Unknown, ...),上游只能看到 UNKNOWN,没法做重试策略或降级判断。
- 服务端返回错误时,必须用
status.Errorf(codes.NotFound, "user %d not found", id)或status.Error(codes.PermissionDenied, "...") - 客户端收到 error 后,要显式解包:
if st, ok := status.FromError(err); ok { switch st.Code() { case codes.NotFound: ... } } - 别用
fmt.Errorf包装 gRPC error,会丢失状态码;拦截器里也需透传status.Status - 流式 RPC 的错误更隐蔽:
Recv()返回非io.EOFerror 才代表流异常终止,需单独处理
多服务注册到同一 Server 时,包名和 service 名不能重复
把 UserServer 和 OrderServer 都注册到一个 grpc.Server 实例没问题,但 proto 定义中 package 和 service 名必须全局唯一,否则 protoc-gen-go-grpc 生成的 register 函数会覆盖。
- 不同服务用不同 proto 文件,各自设独立
package user;、package order; - 生成代码后,注册顺序无关紧要:
pb.RegisterUserServiceServer(srv, us)和pb.RegisterOrderServiceServer(srv, os)可共存 - 若两个 proto 共用同一
package,又都定义了service UserService,则第二个注册会覆盖第一个的 handler - 调试时可用
grpcurl -plaintext localhost:50051 list确认所有 service 是否已暴露
最常被跳过的其实是错误码透传和 keepalive 配置——它们不阻止服务启动,却让问题在压测或上线后才集中爆发,而且现象模糊,容易误判为“网络不稳定”或“业务逻辑偶发失败”。










