gRPC 的 Go 客户端按文档配了 retryPolicy,maxAttempts 设 3,服务端返回 503 时客户端只请求一次就返回,日志里没有任何重试,grpc-go 1.65,服务端也是 Go。

一开始怀疑是「没开 WithDefaultServiceConfig 或 dns resolver」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。retryPolicy 要放在 service config 里而不是 DialOption。还有一种是方法名必须写完整的 /pkg.Service/Method 才匹配。

少数情况下是错误码不在 retryableStatusCodes 列表里。

上来先打印客户端实际生效的 service config

go run ./cmd/client -grpc.debug 2>&1 | grep -i serviceconfig

然后把策略写进完整方法名的 config

python -c "import json;print(json.dumps({'methodConfig':[{'name':[{'service':'order.Order','method':'Get'}],'retryPolicy':{'maxAttempts':3,'initialBackoff':'0.2s','maxBackoff':'2s','backoffMultiplier':2,'retryableStatusCodes':['UNAVAILABLE']}}]}))"

随后用 WithDefaultServiceConfig 显式注入

go run ./cmd/client -serviceconfig ./retry.json

等前面都确认过,再在服务端打点确认收到了三次请求

grep -c 'rpc Get' server.log

别只看报错消失,验证要多做一步。服务端日志里同一请求出现 3 次,客户端最终返回成功,metric 里能看到 retry 计数增加。

gRPC 的重试是服务配置而不是客户端选项,方法名不写全就静默不匹配;配完一定要在服务端数请求次数,光看客户端日志会以为没生效。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189