golang实现简单重试机制的插件库retry-go的使用

Golang实现简单重试机制的插件库retry-go的使用

retry-go是一个简单易用的Golang重试机制库,提供灵活的重试策略配置。

基本用法

HTTP GET带重试机制

url := "http://example.com"
var body []byte

err := retry.Do(
    func() error {
        resp, err := http.Get(url)
        if err != nil {
            return err
        }
        defer resp.Body.Close()
        body, err = ioutil.ReadAll(resp.Body)
        if err != nil {
            return err
        }
        return nil
    },
)

if err != nil {
    // 处理错误
}

fmt.Println(string(body))

带返回值的HTTP GET重试

url := "http://example.com"

body, err := retry.DoWithData(
    func() ([]byte, error) {
        resp, err := http.Get(url)
        if err != nil {
            return nil, err
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            return nil, err
        }

        return body, nil
    },
)

if err != nil {
    // 处理错误
}

fmt.Println(string(body))

高级配置选项

retry-go提供了多种配置选项来自定义重试行为:

设置重试次数

err := retry.Do(
    func() error {
        // 你的代码
    },
    retry.Attempts(5), // 最多重试5次
)

设置重试间隔

err := retry.Do(
    func() error {
        // 你的代码
    },
    retry.Delay(1 * time.Second), // 每次重试间隔1秒
)

设置重试间隔类型

err := retry.Do(
    func() error {
        // 你的代码
    },
    retry.DelayType(retry.BackOffDelay), // 使用指数退避算法
)

重试回调

err := retry.Do(
    func() error {
        return errors.New("some error")
    },
    retry.OnRetry(func(n uint, err error) {
        log.Printf("#%d: %s\n", n, err) // 每次重试时记录
    }),
)

条件重试

err := retry.Do(
    func() error {
        return errors.New("special error")
    },
    retry.RetryIf(func(err error) bool {
        if err.Error() == "special error" {
            return false // 不重试特定错误
        }
        return true
    })
)

错误处理

retry-go返回的错误类型可以包含所有重试过程中遇到的错误:

err := retry.Do(
    func() error {
        return errors.New("original error")
    },
    retry.Attempts(1),
)

fmt.Println(errors.Unwrap(err)) // 输出"original error"

无限重试

设置Attempts(0)可以实现无限重试直到成功:

err := retry.Do(
    func() error {
        // 你的代码
    },
    retry.Attempts(0), // 无限重试
)

上下文支持

可以传入context.Context来控制重试的超时或取消:

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

retry.Do(
    func() error {
        // 你的代码
    },
    retry.Context(ctx),
)

总结

retry-go提供了简单而强大的重试机制,通过灵活的配置选项可以满足各种重试场景需求。无论是简单的HTTP请求重试,还是复杂的业务逻辑重试,retry-go都能提供良好的支持。


更多关于golang实现简单重试机制的插件库retry-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现简单重试机制的插件库retry-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 重试机制库 retry-go 使用指南

retry-go 是一个简单而强大的 Golang 重试库,可以帮助你优雅地实现各种重试逻辑。下面我将详细介绍它的使用方法。

安装

go get github.com/avast/retry-go

基本用法

package main

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

func main() {
	var result string
	err := retry.Do(
		func() error {
			var err error
			result, err = someFunctionThatMightFail()
			return err
		},
		retry.Attempts(3),
		retry.Delay(100*time.Millisecond),
		retry.OnRetry(func(n uint, err error) {
			fmt.Printf("Retry #%d: %v\n", n, err)
		}),
	)

	if err != nil {
		fmt.Printf("Failed after retries: %v\n", err)
	} else {
		fmt.Printf("Success: %s\n", result)
	}
}

func someFunctionThatMightFail() (string, error) {
	// 模拟有时会失败的操作
	if time.Now().Unix()%2 == 0 {
		return "success", nil
	}
	return "", errors.New("temporary error")
}

常用配置选项

retry-go 提供了多种配置选项:

err := retry.Do(
	func() error { /* ... */ },
	retry.Attempts(5),                   // 最大重试次数
	retry.Delay(1*time.Second),          // 基础延迟
	retry.MaxDelay(5*time.Second),       // 最大延迟
	retry.DelayType(retry.BackOffDelay), // 退避延迟策略
	retry.OnRetry(func(n uint, err error) { // 重试回调
		log.Printf("Retry attempt %d: %v", n, err)
	}),
	retry.RetryIf(func(err error) bool { // 判断哪些错误需要重试
		return err.Error() == "temporary error"
	}),
	retry.LastErrorOnly(true),           // 只返回最后一次错误
	retry.Context(ctx),                  // 支持上下文取消
)

延迟策略

retry-go 支持多种延迟策略:

  1. 固定延迟 (默认): retry.DelayType(retry.FixedDelay)
  2. 随机延迟: retry.DelayType(retry.RandomDelay)
  3. 指数退避: retry.DelayType(retry.BackOffDelay)
  4. 组合延迟: retry.DelayType(retry.CombineDelay(retry.BackOffDelay, retry.RandomDelay))

高级示例

package main

import (
	"context"
	"errors"
	"fmt"
	"math/rand"
	"time"

	"github.com/avast/retry-go"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	err := retry.Do(
		func() error {
			return unreliableOperation(ctx)
		},
		retry.Attempts(0), // 0表示无限重试
		retry.MaxDelay(2*time.Second),
		retry.DelayType(retry.BackOffDelay),
		retry.Context(ctx),
		retry.RetryIf(func(err error) bool {
			return errors.Is(err, ErrTemporary)
		}),
	)

	if err != nil {
		fmt.Printf("Operation failed: %v\n", err)
	} else {
		fmt.Println("Operation succeeded!")
	}
}

var ErrTemporary = errors.New("temporary error")

func unreliableOperation(ctx context.Context) error {
	// 模拟有时会失败的操作
	if rand.Intn(10) < 3 {
		return nil
	}
	return ErrTemporary
}

自定义重试逻辑

你可以完全自定义重试逻辑:

type customRetry struct {
	maxAttempts uint
	baseDelay   time.Duration
}

func (r *customRetry) Apply(opts *retry.Config) {
	opts.Attempts = r.maxAttempts
	opts.Delay = r.baseDelay
	opts.OnRetry = func(n uint, err error) {
		fmt.Printf("Custom retry %d: %v\n", n, err)
	}
}

func main() {
	retry.Do(
		func() error { /* ... */ },
		&customRetry{maxAttempts: 5, baseDelay: 1*time.Second},
	)
}

最佳实践

  1. 明确重试条件:使用 RetryIf 明确哪些错误需要重试
  2. 设置合理的重试次数和延迟:避免无限重试或过于频繁的重试
  3. 使用上下文:支持操作取消
  4. 记录重试日志:使用 OnRetry 回调记录重试信息
  5. 区分错误类型:永久性错误不应重试

retry-go 是一个灵活且功能丰富的重试库,通过合理配置可以满足大多数重试场景的需求。

回到顶部