Golang 中强大的重试机制,解决瞬态错误

news2025/1/22 22:43:02

文章精选推荐

1 JetBrains Ai assistant 编程工具让你的工作效率翻倍
2 Extra Icons:JetBrains IDE的图标增强神器
3 IDEA插件推荐-SequenceDiagram,自动生成时序图
4 BashSupport Pro 这个ides插件主要是用来干嘛的 ?
5 IDEA必装的插件:Spring Boot Helper的使用与功能特点
6 Ai assistant ,又是一个写代码神器
7 Cursor 设备ID修改器,你的Cursor又可以继续试用了

文章正文

在 Go 语言中,处理瞬态错误(Transient Errors)是常见的挑战,尤其在网络请求、数据库操作、外部服务调用等场景中。瞬态错误通常是由于临时网络故障、资源竞争或服务不可用等原因引起的,这些错误可能会在一段时间后自动恢复。因此,重试机制在这些情况下非常重要。

Go 语言并没有提供内置的重试机制,但我们可以通过简单的控制结构和一些库来实现高效且灵活的重试机制。下面将介绍如何实现一个强大的重试机制来处理瞬态错误。

1. 基本重试实现

首先,介绍一个简单的重试实现,通过设置最大重试次数和每次重试的间隔时间。

基本重试机制的实现
package main

import (
	"fmt"
	"math/rand"
	"time"
)

// 模拟一个可能失败的操作
func unreliableOperation() error {
	// 模拟随机失败的情况
	if rand.Float32() < 0.7 {
		return fmt.Errorf("transient error")
	}
	return nil
}

// 重试逻辑
func retryOperation(retries int, delay time.Duration) error {
	var err error
	for i := 0; i < retries; i++ {
		err = unreliableOperation()
		if err == nil {
			return nil // 操作成功
		}

		// 打印错误并等待一段时间
		fmt.Printf("Retry %d/%d: %v\n", i+1, retries, err)
		time.Sleep(delay)
	}
	return fmt.Errorf("failed after %d retries: %w", retries, err)
}

func main() {
	rand.Seed(time.Now().UnixNano())

	// 尝试最多 5 次,每次重试间隔 1 秒
	err := retryOperation(5, time.Second)
	if err != nil {
		fmt.Println("Operation failed:", err)
	} else {
		fmt.Println("Operation succeeded")
	}
}
说明:
  • unreliableOperation():模拟一个可能失败的操作,每次调用有 70% 的概率失败。
  • retryOperation():重试操作函数,它会最多重试 retries 次,每次重试之间等待 delay 时间。如果超过最大重试次数,返回错误。
输出示例:
Retry 1/5: transient error
Retry 2/5: transient error
Retry 3/5: transient error
Retry 4/5: transient error
Operation failed: failed after 5 retries: transient error

2. 使用 github.com/cenkalti/backoff

为了更灵活、优雅地实现重试机制,Go 社区有一些优秀的第三方库。其中,backoff 库非常适合处理瞬态错误的重试。它提供了指数退避(Exponential Backoff)策略,这是在处理重试时常用的方式。

安装 backoff
go get github.com/cenkalti/backoff/v4
使用 backoff 库的实现
package main

import (
	"fmt"
	"github.com/cenkalti/backoff/v4"
	"math/rand"
	"time"
)

// 模拟一个可能失败的操作
func unreliableOperation() error {
	// 模拟随机失败的情况
	if rand.Float32() < 0.7 {
		return fmt.Errorf("transient error")
	}
	return nil
}

// 使用 backoff 重试操作
func retryOperationWithBackoff() error {
	// 设置指数退避策略,最大重试间隔为 10 秒
	bo := backoff.NewExponentialBackOff()
	bo.MaxElapsedTime = 30 * time.Second // 最大重试时间限制
	bo.MaxInterval = 10 * time.Second   // 最大间隔时间

	// 定义重试逻辑
	return backoff.Retry(func() error {
		err := unreliableOperation()
		if err != nil {
			return err // 如果操作失败,返回错误并重试
		}
		return nil // 操作成功
	}, bo)
}

func main() {
	rand.Seed(time.Now().UnixNano())

	err := retryOperationWithBackoff()
	if err != nil {
		fmt.Println("Operation failed:", err)
	} else {
		fmt.Println("Operation succeeded")
	}
}
说明:
  • 指数退避 (Exponential Backoff)backoff.NewExponentialBackOff() 创建了一个指数退避策略,重试间隔会逐渐增加。
  • 最大重试时间限制 (MaxElapsedTime):可以设置一个最大重试时长,超时后停止重试。
  • 最大间隔时间 (MaxInterval):可以限制每次重试的最大间隔时间。
输出示例:
Operation failed: transient error

在此示例中,重试会在失败时以指数级的时间间隔进行,直到成功或者达到最大重试次数为止。


3. 使用 github.com/avast/retry-go

另一个非常流行的库是 retry-go,它提供了简单的 API 来实现重试机制。此库支持自定义重试次数、延迟、间隔策略等。

安装 retry-go
go get github.com/avast/retry-go
使用 retry-go 库的实现
package main

import (
	"fmt"
	"github.com/avast/retry-go"
	"math/rand"
	"time"
)

// 模拟一个可能失败的操作
func unreliableOperation() error {
	// 模拟随机失败的情况
	if rand.Float32() < 0.7 {
		return fmt.Errorf("transient error")
	}
	return nil
}

// 使用 retry-go 重试操作
func retryOperationWithRetryGo() error {
	// 使用 retry-go 实现重试,最多重试 5 次,每次重试间隔 1 秒
	err := retry.Do(func() error {
		return unreliableOperation()
	}, retry.Attempts(5), retry.Delay(time.Second))

	return err
}

func main() {
	rand.Seed(time.Now().UnixNano())

	err := retryOperationWithRetryGo()
	if err != nil {
		fmt.Println("Operation failed:", err)
	} else {
		fmt.Println("Operation succeeded")
	}
}
说明:
  • retry.Do():执行传入的函数,如果该函数返回错误,将自动重试。
  • retry.Attempts():设置最大重试次数。
  • retry.Delay():设置每次重试之间的延迟时间。
输出示例:
Operation failed: transient error

4. 总结

基本实现:
  • 通过简单的循环、计数器和 time.Sleep() 实现的重试机制,适用于简单的场景。
  • 缺点是没有灵活的退避策略,也没有提供重试次数以外的更多配置选项。
使用 backoff 库:
  • 提供了指数退避机制,适用于需要更精细控制重试时间间隔的场景。
  • 支持最大重试时间、最大间隔时间等更多配置选项。
使用 retry-go 库:
  • 提供了非常简单易用的接口,能够快速实现重试。
  • 支持多种延迟策略和重试配置,适合快速开发。

根据不同的需求选择合适的库或实现方式。对于需要精细控制的场景,推荐使用 backoffretry-go 库;对于简单场景,基本的重试机制足够。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2280580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证8)

为进一步测试通过请求头传递token进行身份验证&#xff0c;在main.htm中增加layui的数据表格组件&#xff0c;并调用后台服务分页显示数据&#xff0c;后台分页查询数据接口如下所示&#xff08;测试时&#xff0c;直接将数据写死到代码中&#xff0c;没有查询数据库&#xff0…

Python新春烟花

目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…

【leetcode 24】151.翻转字符串里的单词==❗没看懂❗==

思路&#xff1a; 一些同学会使用split库函数&#xff0c;分隔单词&#xff0c;然后定义一个新的string字符串&#xff0c;最后再把单词倒序相加&#xff0c;那么这道题题目就是一道水题了&#xff0c;失去了它的意义。 所以这里我还是提高一下本题的难度&#xff1a;不要使用辅…

STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态

STM32W5500以太网应用开发003_TCP服务器添加OLED&#xff08;u8g2&#xff09;显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…

Oracle审计

审计是监控选定的用户数据库操作的过程 审计的目的&#xff1a; 调查可疑的数据库活动&#xff1a; 审计可以帮助检测和跟踪潜在的 security breaches、未授权的访问尝试或其他异常行为。通过分析审计日志&#xff0c;可以确定可疑活动的来源、时间、频率和影响。 收集特定数…

智能新浪潮:亚马逊云科技发布Amazon Nova模型

在2024亚马逊云科技re:Invent全球大会上&#xff0c;亚马逊云科技宣布推出新一代基础模型Amazon Nova&#xff0c;其隶属于Amazon Bedrock&#xff0c;这些模型精准切入不同领域&#xff0c;解锁多元业务可能&#xff0c;为人工智能领域带来革新。 带你认识一起了解Amazon Nova…

2025 OWASP十大智能合约漏洞

随着去中心化金融&#xff08;DeFi&#xff09;和区块链技术的不断发展&#xff0c;智能合约安全的重要性愈发凸显。在此背景下&#xff0c;开放网络应用安全项目&#xff08;OWASP&#xff09;发布了备受期待的《2025年智能合约十大漏洞》报告。 这份最新报告反映了不断演变的…

力扣面试经典题

目录 前言 一、合并两个有序数组 二、移除元素 三、删除有序数组的重复项 四、删除有序数组的重复项Ⅱ 五、取数组中出现次数大于数组长度/2的元素 六、移动数组元素 七、计算数组中相差最大的值 八、字母异位词分组 九、最长连续序列 十、移动0 十一、盛水最多的容…

【RabbitMq】RabbitMq高级特性-延迟消息

延迟消息 什么是延迟消息死信交换机延迟消息插件-DelayExchange其他文章 什么是延迟消息 延迟消息&#xff1a;发送者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而是在指定时间之后才收到消息。 延迟任务&#xff1a;设置在一定时间之后才执行的任…

抖音小程序一键获取手机号

前端代码组件 <button v-if"!isFromOrderList"class"get-phone-btn" open-type"getPhoneNumber"getphonenumber"onGetPhoneNumber">一键获取</button>// 获取手机号回调onGetPhoneNumber(e) {var that this tt.login({f…

CSS:语法、样式表、选择器

目录 一、语法 二、创建 外部样式表 内部样式表 内联样式 三、选择器 ID选择器 类选择器 伪类选择器 :hover a:link a:active a:visited 属性选择器 伪元素选择器 ::first-letter ::first-line ::selection ::placeholder ::before 和::after 通配选择器 标…

配电自动化中的进线监控技术

进线监控技术是配电网自动化中的一项关键技术&#xff0c;它主要用于对配电网进线变电站的开关状态以及母线电压、电流、有功功率、无功功率及电度量等参数进行实时监测。以下是对进线监控技术的详细介绍&#xff1a; 一、技术原理 进线监控技术基于传感器技术、数据采集技术、…

【三维分割】Gaga:通过3D感知的 Memory Bank 分组任意高斯

文章目录 摘要一、引言二、主要方法2.1 3D-aware Memory Bank2.2 三维分割的渲染与下游应用 三、实验消融实验应用: Scene Manipulation 地址&#xff1a;https://www.gaga.gallery 标题&#xff1a;Gaga: Group Any Gaussians via 3D-aware Memory Bank 来源&#xff1a;加利福…

《王者荣耀》皮肤爬虫源码

1.爬取网页 https://pvp.qq.com/web201605/herolist.shtml 2.python代码 import requests from bs4 import BeautifulSoup import os import threading from queue import Queuedef mul(x):if not os.path.exists(x):os.mkdir(x)print("目录创建成功")else:pass h…

iconfont等图标托管网站上传svg显示未轮廓化解决办法

打开即时设计 即时设计 - 可实时协作的专业 UI 设计工具 导入图标后拖入画板里面&#xff0c;右键选择轮廓化 将图标导出

【Linux系列】查看服务器是否使用了 SSD 的多种方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【AIGC】ChatGPT 的 Prompt Hacker 技巧:让简历轻松通过 AI 筛选

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;背景简化简历格式 &#x1f4af;简化 Prompt Hacker 的逻辑使用 Prompt Hacker 技巧**示例 Prompt&#xff1a;引导 AI 筛选简历**如何利用 Prompt 优化简历筛…

AI News(1/21/2025):OpenAI 安全疏忽:ChatGPT漏洞引发DDoS风险/OpenAI 代理工具即将发布

1、OpenAI 的安全疏忽&#xff1a;ChatGPT API 漏洞引发DDoS风险 德国安全研究员 Benjamin Flesch 发现了一个严重的安全漏洞&#xff1a;攻击者可以通过向 ChatGPT API 发送一个 HTTP 请求&#xff0c;利用 ChatGPT 的爬虫对目标网站发起 DDoS 攻击。该漏洞源于 OpenAI 在处理…

windows下使用docker执行器并配置 hosts 解析

本篇目录 1. 问题背景2. 环境准备2.1 云上开通windows 2022 英文版机器2.1.1 安装 git2.1.2 安装 runner2.1.3 装docker2.1.4 注册runner并使用docker执行器 3. 项目信息3.1 编写window bat脚本3.2 项目.gitlab-ci.yml文件 4. 测试结论4.1 运行流水线 5. troubleshooting问题1&…

centos9编译安装opensips 二【进阶篇-定制目录+模块】推荐

环境&#xff1a;centos9 last opensips -V version: opensips 3.6.0-dev (x86_64/linux) flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, Q_MALLOC, F_MALLOC, HP_MALLOC, DBG_MALLOC, CC_O0, FAST_LOCK-ADAPTIVE_WAIT ADAPTIVE_WAIT_LOOPS1024, MAX_RE…