识别可重试错误如超时、连接拒绝;2. 使用循环与休眠实现重试;3. 控制最大重试次数避免无限重试。
在使用 golang 的 RPC 调用时,网络抖动、服务短暂不可用等问题可能导致调用失败。为了提高系统的稳定性,需要对异常的 RPC 调用进行重试。关键在于识别可重试的错误、控制重试次数和间隔,并避免对非幂等操作造成副作用。
识别可重试的错误类型
并不是所有错误都适合重试。比如参数错误或方法不存在属于客户端逻辑问题,重试无意义。应重点关注网络相关错误:
- 连接超时、读写超时
- 连接被拒绝或断开(如 i/o timeout、connection refused)
- 服务端无响应或返回临时错误码
可以通过检查错误信息中的关键字来判断是否可重试:
if strings.Contains(err.Error(), "timeout") || strings.Contains(err.Error(), "connection refused") { /* 可重试 */ }
实现简单的重试逻辑
使用 for 循环结合 time.Sleep 实现基本重试机制:
立即学习“go语言免费学习笔记(深入)”;
func rpcCallWithRetry(client *rpc.Client, method string, args, reply interface{}, maxRetries int) error { var err error for i := 0; i
其中 isRetryable 函数用于判断错误是否可重试。
考虑幂等性与上下文控制
重试只适用于幂等操作(多次执行结果一致)。对于修改数据的操作,需服务端支持去重或客户端携带唯一请求 ID。
使用 context 控制整体超时,避免因多次重试导致总耗时过长:
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel()
for ctx.Err() == nil { err := client.Call(method, args, reply) if err == nil { break } if !isRetryable(err) { return err } select { case <-time.After(50 * time.Millisecond): case <-ctx.Done(): } }
基本上就这些。合理设置重试次数(如 2~3 次)、采用指数退避、区分错误类型,再结合上下文超时控制,就能有效提升 RPC 调用的容错能力。不复杂但容易忽略细节。
go golang ai golang String if for Error int 循环 Interface var rpc