Aracılığıyla paylaş


Dayanıklı İşlevler hatalarını işleme (Azure İşlevleri)

Dayanıklı İşlev düzenlemeleri kodda uygulanır ve programlama dilinin yerleşik hata işleme özelliklerini kullanabilir. Düzenlemelerinize hata işleme ve telafi eklemek için öğrenmeniz gereken yeni kavramlar yoktur. Ancak, bilmeniz gereken birkaç davranış vardır.

Not

Azure İşlevleri için Node.js programlama modelinin 4. sürümü genel olarak kullanılabilir. Yeni v4 modeli, JavaScript ve TypeScript geliştiricileri için daha esnek ve sezgisel bir deneyime sahip olacak şekilde tasarlanmıştır. Geçiş kılavuzunda v3 ve v4 arasındaki farklar hakkında daha fazla bilgi edinin.

Aşağıdaki kod parçacıklarında JavaScript (PM4), yeni deneyim olan programlama modeli V4'i belirtir.

Etkinlik işlevlerinde ve alt düzenlemelerde hatalar

Dayanıklı İşlevler'de, etkinlik işlevleri veya alt düzenlemelerde oluşan işlenmeyen özel durumlar, standartlaştırılmış özel durum türleri kullanılarak orchestrator işlevine geri sıralanır.

Örneğin, iki hesap arasında fon aktarımı gerçekleştiren aşağıdaki orchestrator işlevini göz önünde bulundurun:

Dayanıklı İşlevler C# süreç içi, işlenmeyen özel durumlar FunctionFailedException olarak fırlatılır.

Özel durum iletisi genellikle hataya hangi etkinlik işlevlerinin veya alt düzenlemelerin neden olduğunu tanımlar. Daha ayrıntılı hata bilgilerine erişmek için özelliğini inceleyin InnerException .

[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var transferDetails = context.GetInput<TransferOperation>();

    await context.CallActivityAsync("DebitAccount",
        new
        {
            Account = transferDetails.SourceAccount,
            Amount = transferDetails.Amount
        });

    try
    {
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.DestinationAccount,
                Amount = transferDetails.Amount
            });
    }
    catch (FunctionFailedException)
    {
        // Refund the source account.
        // Another try/catch could be used here based on the needs of the application.
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.SourceAccount,
                Amount = transferDetails.Amount
            });
    }
}

Not

Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.

İlk CreditAccount işlev çağrısı başarısız olursa orchestrator işlevi, fonları kaynak hesaba geri yatırarak telafi eder.

Varlık işlevlerindeki hatalar

Varlık işlevleri için özel durum işleme davranışı Dayanıklı İşlevler barındırma modeline göre farklılık gösterir:

İşlemde C# kullanan Dayanıklı İşlevler'de, varlık işlevleri tarafından oluşan özgün özel durum türleri doğrudan düzenleyiciye döndürülür.

[FunctionName("Function1")]
public static async Task<string> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    try
    {
        var entityId = new EntityId(nameof(Counter), "myCounter");
        await context.CallEntityAsync(entityId, "Add", 1);
    }
    catch (Exception ex)
    {
        // The exception type will be InvalidOperationException with the message "this is an entity exception".
    }
    return string.Empty;
}

[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
    switch (ctx.OperationName.ToLowerInvariant())
    {
        case "add":
            throw new InvalidOperationException("this is an entity exception");
        case "get":
            ctx.Return(ctx.GetState<int>());
            break;
    }
}

Hatada otomatik yeniden deneme

Etkinlik işlevlerini veya alt düzenleme işlevlerini çağırdığınızda, otomatik bir yeniden deneme ilkesi belirtebilirsiniz. Aşağıdaki örnek, bir işlevi en fazla üç kez çağırmayı dener ve her yeniden deneme arasında 5 saniye bekler:

[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var retryOptions = new RetryOptions(
        firstRetryInterval: TimeSpan.FromSeconds(5),
        maxNumberOfAttempts: 3);

    await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);

    // ...
}

Not

Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.

Önceki örnekteki etkinlik işlevi çağrısı, otomatik yeniden deneme ilkesini yapılandırmak için bir parametre alır. Otomatik yeniden deneme ilkesini özelleştirmek için çeşitli seçenekler vardır:

  • En fazla deneme sayısı: En fazla deneme sayısı. 1 olarak ayarlanırsa yeniden deneme olmaz.
  • İlk yeniden deneme aralığı: İlk yeniden deneme denemesi öncesinde bek süre.
  • Geri alma katsayısı: Geri alma artış oranını belirlemek için kullanılan katsayı. Varsayılan değer 1'tir.
  • En fazla yeniden deneme aralığı: Yeniden deneme denemeleri arasında bekleme süresi üst sınırı.
  • Yeniden deneme zaman aşımı: Yeniden denemeler yapmak için harcayacak maksimum süre. Varsayılan davranış, süresiz olarak yeniden denemektir.

Özel yeniden deneme işleyicileri

.NET veya Java kullanırken kodda yeniden deneme işleyicileri uygulama seçeneğiniz de vardır. Bildirim temelli yeniden deneme ilkeleri yeterince açıklayıcı olmadığında bu yararlı olur. Özel yeniden deneme işleyicilerini desteklemeyen diller için yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak yeniden deneme ilkeleri uygulama seçeneğiniz vardır.

RetryOptions retryOptions = new RetryOptions(
    firstRetryInterval: TimeSpan.FromSeconds(5),
    maxNumberOfAttempts: int.MaxValue)
    {
        Handle = exception =>
        {
            // True to handle and try again, false to not handle and throw.
            if (exception is TaskFailedException failure)
            {
                // Exceptions from TaskActivities are always this type. Inspect the
                // inner Exception to get more details.
            }

            return false;
        };
    }

await ctx.CallActivityWithRetryAsync("FlakeyActivity", retryOptions, null);

İşlev zaman aşımları

Tamamlanması çok uzun sürüyorsa bir orchestrator işlevi içinde işlev çağrısını bırakmak isteyebilirsiniz. Bunu bugün gerçekleştirmenin doğru yolu, aşağıdaki örnekte olduğu gibi "herhangi bir " görev seçici ile dayanıklı bir zamanlayıcı oluşturmaktır:

[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    TimeSpan timeout = TimeSpan.FromSeconds(30);
    DateTime deadline = context.CurrentUtcDateTime.Add(timeout);

    using (var cts = new CancellationTokenSource())
    {
        Task activityTask = context.CallActivityAsync("FlakyFunction");
        Task timeoutTask = context.CreateTimer(deadline, cts.Token);

        Task winner = await Task.WhenAny(activityTask, timeoutTask);
        if (winner == activityTask)
        {
            // success case
            cts.Cancel();
            return true;
        }
        else
        {
            // timeout case
            return false;
        }
    }
}

Not

Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.

Not

Bu mekanizma aslında devam eden etkinlik işlevi yürütmesini sonlandırmaz. Bunun yerine, orchestrator işlevinin sonucu yoksaymasına ve devam etmesine olanak tanır. Daha fazla bilgi için Zamanlayıcılar belgelerine bakın.

İşlenmeyen özel durumlar

Orchestrator işlevi işlenmeyen bir özel durumla başarısız olursa, özel durumun ayrıntıları günlüğe kaydedilir ve örnek bir Failed durumla tamamlar.

FailureDetails için Özel Durum Özellikleri Ekle (.NET Yalıtılmış)

.NET Yalıtılmış modelinde Dayanıklı Görev iş akışları çalıştırılırken, görev hataları otomatik olarak failureDetails nesnesine serileştirilir. Varsayılan olarak, bu nesne aşağıdaki gibi standart alanları içerir:

  • ErrorType — özel durum türü adı
  • İleti — özel durum iletisi
  • StackTrace — serileştirilmiş yığın izlemesi
  • InnerFailure – özyinelemeli iç özel durumlar için iç içe bir FailureDetails nesnesi

Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0'dan başlayarak, bir IExceptionPropertiesProvider ( v1.16.1paketinden başlayarak Microsoft.DurableTask.Worker'da tanımlanır) uygulayarak bu davranışı genişletebilirsiniz. Bu sağlayıcı, FailureDetails.Properties sözlüğüne hangi özel durum türlerinin ve hangi özelliklerinin dahil edilmesi gerektiğini tanımlar.

Not

  • Bu özellik yalnızca .NET Yalıtılmış'da kullanılabilir. Java desteği gelecek bir sürümde eklenecektir.
  • Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0 veya üzerini kullandığınızdan emin olun.
  • Microsoft.DurableTask.Worker v1.16.1 veya üzerini kullandığınızdan emin olun.

Özel Durum Özellikleri Sağlayıcısını Gerçekleştirmek

Önemsediğiniz özel durumlar için seçili özellikleri ayıklamak ve döndürmek için özel bir IExceptionPropertiesProvider uygulayın. Eşleşen bir özel durum türü oluşturulduğunda döndürülen sözlük FailureDetails'in Özellikler alanında serileştirilir.

using Microsoft.DurableTask.Worker;

public class CustomExceptionPropertiesProvider : IExceptionPropertiesProvider
{
    public IDictionary<string, object?>? GetExceptionProperties(Exception exception)
    {
        return exception switch
        {
            ArgumentOutOfRangeException e => new Dictionary<string, object?>
            {
                ["ParamName"] = e.ParamName,
                ["ActualValue"] = e.ActualValue
            },
            InvalidOperationException e => new Dictionary<string, object?>
            {
                ["CustomHint"] = "Invalid operation occurred",
                ["TimestampUtc"] = DateTime.UtcNow
            },
            _ => null // Other exception types not handled
        };
    }
}

Sağlayıcıyı Kaydetme

Özel IExceptionPropertiesProvider'ınızı .NET Yalıtılmış çalışan konağınıza( genellikle Program.cs) kaydedin:

using Microsoft.DurableTask.Worker;
using Microsoft.Extensions.DependencyInjection;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder =>
    {
        // Register custom exception properties provider
        builder.Services.AddSingleton<IExceptionPropertiesProvider, CustomExceptionPropertiesProvider>();
    })
    .Build();

host.Run();

Kaydedildikten sonra, işlenen türlerden biriyle eşleşen herhangi bir özel durum, yapılandırılan özellikleri FailureDetails'e otomatik olarak ekler.

Örnek Hata Detayları Çıkışı

Sağlayıcınızın yapılandırmasıyla eşleşen bir özel durum oluştuğunda, düzenleme aşağıdaki gibi serileştirilmiş bir FailureDetails yapısı alır:

{
  "errorType": "TaskFailedException",
  "message": "Activity failed with an exception.",
  "stackTrace": "...",
  "innerFailure": {
    "errorType": "ArgumentOutOfRangeException",
    "message": "Specified argument was out of range.",
    "properties": {
      "ParamName": "count",
      "ActualValue": 42
    }
  }
}

Sonraki adımlar