Eşzamansız işlevleri yeniden deneme

Bu dokümanda, eşzamansız (HTTPS olmayan) arka plan işlevlerinin hata durumunda yeniden denemesini nasıl isteyebileceğiniz açıklanmaktadır.

Etkinliğe dayalı işlevlerin tamamlanamamasının nedenleri

Nadir durumlarda, dahili bir hata nedeniyle bir işlev erken sonlandırılabilir ve varsayılan olarak işlev otomatik olarak yeniden denenebilir veya denenmeyebilir.

Daha yaygın olarak, işleve dayalı bir işlev, işlev kodunun kendisinde oluşan hatalar nedeniyle başarıyla tamamlanamayabilir. Bunun olası nedenleri şunlardır:

  • İşlevde bir hata vardır ve çalışma zamanı bir istisna oluşturur.
  • İşlev, bir hizmet uç noktasına ulaşamıyor veya ulaşmaya çalışırken zaman aşımına uğruyor.
  • İşlev, kasıtlı olarak bir istisna oluşturur (örneğin, bir parametre doğrulanamadığında).
  • Node.js işlevi, reddedilen bir promise döndürür veya geri çağırmaya null olmayan bir değer iletir.

Yukarıdaki durumlardan herhangi birinde işlev yürütmeyi durdurur ve hata döndürür. Mesajları üreten etkinlik tetikleyiciler, işlevinizin ihtiyaçlarını karşılayacak şekilde özelleştirebileceğiniz yeniden deneme politikalarına sahiptir.

Yeniden denemenin anlamı

Cloud Functions, bir etkinlik kaynağı tarafından yayınlanan her etkinlik için etkinliğe dayalı bir işlevin en az bir kez yürütülmesini sağlar. Varsayılan olarak, bir işlev çağrısı hatayla sonlanırsa işlev tekrar çağrılmaz ve etkinlik silinir. Etkinliğe dayalı bir işlevde yeniden denemeleri etkinleştirdiğinizde Cloud Functions, başarısız olan işlev çağrısını başarıyla tamamlanana veya yeniden deneme süresi dolana kadar yeniden dener.

Bir işlev için yeniden denemeler etkinleştirilmediğinde (varsayılan ayar budur) işlev her zaman başarıyla yürütüldüğünü bildirir ve günlüklerinde 200 OK yanıt kodları görünebilir. Bu durum, işlevde bir hatayla karşılaşılsa bile gerçekleşir. İşlevinizde hata oluştuğunda bunu net bir şekilde belirtmek için hataları uygun şekilde bildirdiğinizden emin olun.

Yeniden denemeleri işlev kodunuzdan yapılandırma

Cloud Functions for Firebase ile bir işlevin kodunda yeniden denemeleri etkinleştirebilirsiniz. Yeni bir Firestore dokümanı oluşturma gibi bir arka plan etkinliği için bunu yapmak istiyorsanız failurePolicy (1. nesil) veya retry politikasını (2. nesil) true olarak ayarlayın:

1. nesil

exports.docCreated = functions
  .runWith({
    // retry on failure
    failurePolicy: true,
  })
  .firestore.document("my-collection/{docId}")
  .onCreate((change, context) => {
    /* ... */
  });

2. nesil

const { onDocumentCreated } = require("firebase-functions/firestore");

exports.docCreated = onDocumentCreated(
  {
    // retry on failure
    retry: true,
  },
  "my-collection/{docId}",
  (event) => {
    /* ... */
  },
);

true ayarını gösterildiği gibi yapılandırmak, bir işlevi hata durumunda yeniden denenecek şekilde yapılandırır.

Yeniden deneme aralığı

2. nesil işlevlerde bu yeniden deneme süresi 24 saat sonra sona erer. 1. nesil işlevler için bu süre 7 gündür. Cloud Functions, yeni oluşturulan etkinliğe dayalı işlevleri, 10 ila 600 saniye arasında artan bir geri yükleme süresiyle eksponansiyel geri yükleme stratejisi kullanarak yeniden dener. Bu politika, yeni işlevlere ilk kez dağıttığınızda uygulanır. Bu değişiklik, bu sürüm notunda açıklanan değişiklikler yürürlüğe girmeden önce dağıtılan mevcut işlevlere geriye dönük olarak uygulanmaz. İşlevleri yeniden dağıtsanız bile bu durum geçerlidir.

En iyi uygulamalar

Bu bölümde, yeniden denemeleri kullanmayla ilgili en iyi uygulamalar açıklanmaktadır.

Geçici hataları işlemek için yeniden deneme özelliğini kullanma

İşleviniz başarıyla yürütülene kadar sürekli olarak yeniden denendiğinden, yeniden denemeleri etkinleştirmeden önce test yoluyla kodunuzdaki hatalar gibi kalıcı hataları ortadan kaldırmanız gerekir. Yeniden denemeler, yeniden denendiğinde çözülme olasılığı yüksek olan aralıklı veya geçici hataları (ör. kararsız hizmet uç noktası veya zaman aşımı) ele almak için en iyi yöntemdir.

Sonsuz yeniden deneme döngülerini önlemek için bir bitiş koşulu belirleyin.

Yeniden denemeleri kullanırken işlevinizi sürekli döngüye karşı korumak en iyi uygulamadır. Bunu, işlev işlemeye başlamadan önce iyi tanımlanmış bir bitiş koşulu ekleyerek yapabilirsiniz. Bu tekniğin yalnızca işleviniz başarıyla başlatılırsa ve bitiş koşulunu değerlendirebiliyorsa işe yarayacağını unutmayın.

Basit ama etkili bir yaklaşım, belirli bir süreden daha eski zaman damgalarına sahip etkinlikleri silmektir. Bu sayede, hatalar kalıcı olduğunda veya beklenenden uzun sürdüğünde aşırı yürütme önlenir.

Örneğin, bu kod snippet'i 10 saniyeden eski tüm etkinlikleri siler:

const eventAgeMs = Date.now() - Date.parse(event.timestamp);
const eventMaxAgeMs = 10000;
if (eventAgeMs > eventMaxAgeMs) {
  console.log(`Dropping event ${event} with age[ms]: ${eventAgeMs}`);
  callback();
  return;
}

catch'i Promise'lerle kullanma

İşlevinizde yeniden denemeler etkinleştirilmişse işlenmeyen tüm hatalar yeniden denemeyi tetikler. Kodunuzun, yeniden denemeyle sonuçlanmaması gereken hataları yakaladığından emin olun.

Yapmanız gerekenlere dair bir örnek:

return doFooAsync().catch((err) => {
    if (isFatal(err)) {
        console.error(`Fatal error ${err}`);
    }
    return Promise.reject(err);
});

Yeniden denenebilir etkinliğe dayalı işlevleri idempotent yapma

Yeniden denenebilen etkinlik odaklı işlevler, idempotent olmalıdır. Bu tür bir işlevi eş kuvvetli hale getirmek için bazı genel yönergeler şunlardır:

  • Birçok harici API (ör. Stripe), parametre olarak bir idempotency anahtarı sağlamanıza olanak tanır. Bu tür bir API kullanıyorsanız etkinlik kimliğini idempotency anahtarı olarak kullanmanız gerekir.
  • Idempotency, en az bir kez teslimatla iyi çalışır çünkü yeniden denemeyi güvenli hale getirir. Güvenilir kod yazmak için genel olarak en iyi uygulama, eş kuvvetliliği yeniden denemelerle birleştirmektir.
  • Kodunuzun dahili olarak eş kuvvetli olduğundan emin olun. Örneğin:
    • Değişikliklerin, sonucu değiştirmeden birden fazla kez gerçekleşebildiğinden emin olun.
    • Durumu değiştirmeden önce bir işlemde veritabanı durumunu sorgulama
    • Tüm yan etkilerin de aynı şekilde idempotent olduğundan emin olun.
  • İşlevin dışında, koddan bağımsız bir işlem kontrolü uygulayın. Örneğin, belirli bir etkinlik kimliğinin zaten işlendiğini kaydeden bir yerde durumu koruyun.
  • Yinelenen işlev çağrılarını bant dışı olarak işleyin. Örneğin, yinelenen işlev çağrılarından sonra temizleme yapan ayrı bir temizleme işlemi kullanın.

Yeniden deneme politikasını yapılandırma

İşlevinizin ihtiyaçlarına bağlı olarak yeniden deneme politikasını doğrudan yapılandırmak isteyebilirsiniz. Bu sayede, aşağıdakilerin herhangi bir kombinasyonunu ayarlayabilirsiniz:

  • Yeniden deneme aralığını 7 günden 10 dakikaya kadar kısaltın.
  • Üstel geri yükleme yeniden deneme stratejisi için minimum ve maksimum geri yükleme süresini değiştirme
  • Yeniden deneme stratejisini hemen yeniden deneyecek şekilde değiştirin.
  • İletilemeyen ileti konusu yapılandırın.
  • Maksimum ve minimum teslimat denemesi sayısı belirleyin.

Yeniden deneme politikasını yapılandırmak için:

  1. HTTP işlevi yazma
  2. İşlevin URL'sini hedef olarak belirterek Pub/Sub aboneliği oluşturmak için Pub/Sub API'sini kullanın.

Pub/Sub'i doğrudan yapılandırma hakkında daha fazla bilgi için Pub/Sub hataları ele alma ile ilgili belgelere bakın.