Chapter 1: Go'da Tekrar Denemesine Giriş
1.1 Tekrar Deneme Mekanizmalarının İhtiyacının Anlaşılması
Birçok hesaplama senaryosunda, özellikle dağıtılmış sistemlerle veya ağ ile iletişimde bulunurken, işlemler geçici hatalar nedeniyle başarısız olabilir. Bu hatalar genellikle ağ kararsızlığı, bir hizmetin kısa süreli kullanılamaması veya zaman aşımı gibi geçici sorunlardır. Hemen başarısız olmak yerine, sistemler geçici hatalarla karşılaşan işlemleri tekrar denemek üzere tasarlanmalıdır. Bu yaklaşım, güvenilirlik ve dayanıklılığı artırır.
Tekrar deneme mekanizmaları, işlemlerin tutarlılığı ve tamamlanması gereken uygulamalarda önemli olabilir. Ayrıca, son kullanıcıların deneyimlediği hata oranını azaltabilirler. Ancak, tekrar deneme mekanizmasını uygulamak, ne sıklıkla ve ne kadar süreyle tekrar deneneceğine karar verme gibi zorluklarla birlikte gelir. İşte burada, geri çekilme stratejileri önemli bir rol oynar.
1.2 go-retry
Kütüphanesinin Genel Bakışı
Go'daki go-retry
kütüphanesi, çeşitli geri çekilme stratejileri ile uygulamalarınıza tekrarlama mantığı eklemenin esnek bir yolunu sağlar. Temel özellikler şunları içerir:
- Genişletilebilirlik: Go'nun
http
paketi gibi,go-retry
genişletilebilir olacak şekilde tasarlanmıştır. Kendi geri çekilme işlevlerinizi yazabilir veya sağlanan kullanışlı filtrelerden yararlanabilirsiniz. - Bağımsızlık: Kütüphane, yalnızca Go standart kitaplığına dayanır ve dış bağımlılıklardan kaçınarak projenizi hafif tutar.
- Eşzamanlılık: Eşzamanlı kullanım için güvenlidir ve herhangi ekstra zahmet olmaksızın gorutinlerle çalışabilir.
- Bağlam odaklı: Zaman aşımı ve iptal için Go'nun yerel bağlamlarını destekler ve Go'nun eşzamanlılık modeliyle sorunsuz entegre olur.
Chapter 2: Kütüphanelerin İçe Aktarılması
go-retry
kütüphanesini kullanmadan önce, projenize içe aktarılması gerekmektedir. Bunun için, modülünüze bağımlılıkları eklemek için Go komutu olan go get
kullanılabilir. Basitçe terminalinizi açın ve şunu çalıştırın:
go get github.com/sethvargo/go-retry
Bu komut, go-retry
kütüphanesini alacak ve projenizin bağımlılıklarına ekleyecektir. Bundan sonra, kodunuzu diğer herhangi bir Go paketi gibi içe aktarabilirsiniz.
Chapter 3: Temel Tekrar Deneme Mantığının Uygulanması
3.1 Sabit Geri Çekilme ile Basit Tekrar Deneme
En basit tekrarlama mantığı, her tekrar deneme arasında sabit bir süre beklemeyi içerir. go-retry
ile sabit geri çekilme kullanarak tekrar denemeleri gerçekleştirebilirsiniz.
İşte go-retry
ile sabit geri çekilme kullanımı örneği:
package main
import (
"context"
"time"
"github.com/sethvargo/go-retry"
)
func main() {
ctx := context.Background()
// Yeni sabit geri çekilme oluştur
backoff := retry.NewConstant(1 * time.Second)
// Tekrar deneme mantığını, retry.Do'ya iletilen bir işlev içinde sarmalayın
operation := func(ctx context.Context) error {
// Kodunuz burada. Tekrar denemek için retry.RetryableError(err) veya durdurmak için nil döndürün.
// Örnek:
// err := someOperation()
// if err != nil {
// return retry.RetryableError(err)
// }
// return nil
return nil
}
// İstenen bağlam, geri çekilme stratejisi ve işlemle retry.Do kullanın
if err := retry.Do(ctx, backoff, operation); err != nil {
// Hata ile başa çıkın
}
}
Bu örnekte, retry.Do
işlevi, başarılı olana kadar veya bağlam zaman aşımına uğrayana veya iptal edilene kadar operation
işlevini her 1 saniyede bir deneyecektir.
3.2 Üstel Geri Çekilme Uygulama
Üstel geri çekilme, tekrar denemeler arasındaki bekleme süresini üstel olarak artırır. Bu strateji, sisteme yükü azaltmaya yardımcı olur ve özellikle büyük ölçekli sistemler veya bulut hizmetleri ile uğraşırken çok yararlıdır.
go-retry
ile üstel geri çekilmenin nasıl kullanılacağı aşağıdaki gibidir:
package main
import (
"context"
"time"
"github.com/sethvargo/go-retry"
)
func main() {
ctx := context.Background()
// Yeni üstel geri çekilme oluştur
backoff := retry.NewExponential(1 * time.Second)
// Tekrar denenebilir işlemi sağlayın
operation := func(ctx context.Context) error {
// Önceki gösterildiği gibi işlemi uygulayın
return nil
}
// Üstel geri çekilme ile işlemi gerçekleştirmek için retry.Do kullanın
if err := retry.Do(ctx, backoff, operation); err != nil {
// Hata ile başa çıkın
}
}
Üstel geri çekilmede, başlangıç geri çekilme 1 saniye olarak ayarlanmışsa, tekrar denemeler 1sn, 2sn, 4sn vs. şeklinde, üstel olarak artan bir bekleme süresine sahip olacaktır.
3.3 Fibonacci Geri Çekilme Stratejisi
Fibonacci geri çekilme stratejisi, yeniden denemeler arasındaki bekleme süresini belirlemek için Fibonacci dizisini kullanır; bu, aşamalı olarak artan bir zaman aşımının faydalı olduğu ağ ile ilgili sorunlar için iyi bir strateji olabilir.
go-retry
ile Fibonacci geri çekilmesinin uygulanması aşağıda gösterilmiştir:
package main
import (
"context"
"time"
"github.com/sethvargo/go-retry"
)
func main() {
ctx := context.Background()
// Yeni bir Fibonacci geri çekilme oluştur
geriÇekilme := retry.NewFibonacci(1 * time.Second)
// Yeniden denenecek bir işlemi tanımla
işlem := func(ctx context.Context) error {
// Burada, başarısız olabilecek ve yeniden denemeye ihtiyaç duyan eylemi gerçekleştirme mantığı olacaktı
return nil
}
// Fibonacci geri çekilme ile işlemi yeniden dene ve retry.Do kullan
if err := retry.Do(ctx, geriÇekilme, işlem); err != nil {
// Hata ile başa çık
}
}
Başlangıç değeri 1 saniye olan Fibonacci geri çekilme ile, yeniden denemeler Fibonacci dizisini takip ederek 1s, 1s, 2s, 3s, 5s vb. sonrasında gerçekleşecektir.
Bölüm 4: Gelişmiş Yeniden Deneme Teknikleri ve Aracı Yazılımları
4.1 Yeniden Denemelerde Jitter Kullanımı
Yeniden deneme mantığını uygularken, sistem üzerinde eş zamanlı yeniden denemelerin etkisini göz önünde bulundurmak önemlidir; bu durum, bir yıldırım sürüsü problemine yol açabilir. Bu sorunu hafifletmek için, geri çekilme aralıklarına rastgele jitter ekleyebiliriz. Bu teknik, yeniden deneme girişimlerini zamanlamak için yardımcı olur ve birden fazla istemcinin aynı anda yeniden denemede bulunma olasılığını azaltır.
Jitter eklemenin bir örneği:
b := retry.NewFibonacci(1 * time.Second)
// Bir sonraki değeri, +/- 500ms olarak döndür
b = retry.WithJitter(500 * time.Millisecond, b)
// Bir sonraki değeri, sonucun %5'i kadar +/- döndür
b = retry.WithJitterPercent(5, b)
4.2 Maksimum Yeniden Deneme Sayısının Belirlenmesi
Bazı senaryolarda, uzun ve etkisiz yeniden denemeleri engellemek için yeniden deneme girişimlerinin sayısını sınırlandırmak gereklidir. Maksimum yeniden deneme sayısını belirterek, işlemden vazgeçmeden önce deneme sayısını kontrol altına alabiliriz.
Maksimum yeniden deneme belirleme örneği:
b := retry.NewFibonacci(1 * time.Second)
// 5. deneme başarısız olduğunda, 4 yeniden deneme sonunda dur
b = retry.WithMaxRetries(4, b)
4.3 Bireysel Geri Çekilme Sürelerinin Sınırlanması
Bireysel geri çekilme sürelerinin belirli bir eşiği aşmamasını sağlamak için CappedDuration
aracı yazılımını kullanabiliriz. Bu, aşırı derecede uzun geri çekilme aralıklarının hesaplanmasını önler ve yeniden deneme davranışına öngörülebilirlik katar.
Bireysel geri çekilme sürelerinin sınırlanması örneği:
b := retry.NewFibonacci(1 * time.Second)
// Maksimum değerin 2 saniye olmasını sağla
b = retry.WithCappedDuration(2 * time.Second, b)
4.4 Toplam Yeniden Deneme Süresinin Kontrolü
Tüm yeniden deneme süreci için belirli bir süre sınırı olması gereken senaryolarda, toplam yürütme süresi için WithMaxDuration
aracı yazılımını kullanarak maksimum toplam yürütme süresini belirleyebiliriz. Bu, yeniden deneme sürecinin sonsuzca devam etmemesini sağlayarak, yeniden denemelere bir süre bütçesi uygular.
Toplam yeniden deneme süresinin kontrolü örneği:
b := retry.NewFibonacci(1 * time.Second)
// Maksimum toplam yeniden deneme süresi 5 saniye olacak şekilde ayarla
b = retry.WithMaxDuration(5 * time.Second, b)