재시도 - 프로세스 중간에서 재시도할 수 있는 Go 패키지 도입

7746 단어 opensourceshowdevgo
이것은 2021년 11월 zenn.dev에 일본어로 처음 게시된 기사를 번역한 것입니다.

개발한 이유



통신, 설치 등 일련의 과정을 단계별로 실행하고 단계별로 재시도를 하고자 할 때가 있었기 때문에 재시도 기능을 일반화하여 패키지로 분리하기로 했습니다.

https://github.com/kenkyu392/go-retry

처음에는 일단 컨텍스트가 취소될 때까지 재시도하는 방식으로 구현했지만 예상대로 현재는 Exponential Backoff 및 최대 재시도 횟수와 같은 최소 요구 사항을 구현하고 있습니다.

용법



이 패키지를 사용하려면 재시도 간격을 설정하는 retry.DurationFuncretry.DoWithContext 에 설정한 다음 실행하려는 프로세스의 각 단계에 대한 함수를 전달하면 됩니다.

package main

import (
    "context"
    "log"

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

func main() {
    // Prepare context for cancellation.
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    errs := retry.DoWithContext(ctx,
        // Retry 5 times while doing Exponential Backoff.
        retry.ExponentialBackoff(5),
        // Separate the process you want to execute into functions
        // for each step and pass them as arguments.
        func(ctx context.Context) error {
            // If something occurs that cannot be retried,
            // the process is canceled with retry.Canceled.
            if failed {
                return retry.Canceled
            }
            return nil
        },
        // If the previous step is successful,
        // proceed to the next step.
        func(ctx context.Context) error {
            return nil
        },
    )

    // Check all errors that occurred during execution.
    for _, err := range errs {
        log.Print(err)
    }
}


지수 백오프란 무엇입니까?



간단히 설명하면 프로세스 실패 횟수에 따라 재시도 간격을 기하급수적으로 늘리는 알고리즘입니다. 재시도 간격을 늘려야 할 필요성에 대해서는 내용을 보면 잘 설명되어 있지만, "처리 충돌 방지"나 "부하 감소"를 위해 구현되는 경우가 많다고 생각합니다.

https://cloud.google.com/iot/docs/how-tos/exponential-backoff

https://docs.aws.amazon.com/general/latest/gr/api-retries.html

재시도 간격 조정 방법



retry.DurationFunc 인터페이스를 사용하여 모든 재시도 간격 알고리즘을 구현할 수 있습니다. 현재 이 패키지는 retry.ExponentialBackoffretry.Duration 표준을 구현합니다.

재시도 간격 조정을 기능으로 만드는 이유는 부분적으로는 간단하게 사용자 정의할 수 있는 구현으로 만들고 싶기 때문이지만 대부분은 지수 백오프의 구현이 다양하기 때문입니다. 예를 들어, retry.ExponentialBackoff의 현재 구현은 200ms + (20ms ~ 100ms)와 같은 임의의 값을 사용하는 알고리즘으로 구현됩니다. Exponential Backoff는 다음과 같이 직접 함수를 구현하여 임의의 값을 사용하지 않고 사용할 수 있습니다.

func ExponentialBackoff(maxRetries int) retry.DurationFunc {
    return func(retries int) time.Duration {
        if maxRetries >= 0 && maxRetries < retries {
            return -1
        }
        return time.Duration(math.Pow(2, float64(retries))*100)*time.Millisecond
    }
}



이 패키지는 대화식 인터페이스가 있는 CLI뿐만 아니라 통신 프로세스, 설치 프로세스, 데이터베이스 등과 함께 사용하도록 설계 및 구현되었습니다. 다양한 장소에 쉽게 통합되도록 설계되었으니, 마음에 드시면 활용하시기 바랍니다.
또한 retry.DurationFunc 및 기타 기여에 대한 추가 또는 제안을 환영합니다.

https://github.com/kenkyu392/go-retry

좋은 웹페이지 즐겨찾기