Aracılığıyla paylaş


Dayanıklı İşlevler'de fan-out/fan-in senaryosu - Bulut yedekleme örneği

Fan-out/fan-in , birden çok işlevi eşzamanlı olarak yürütme ve ardından sonuçlar üzerinde bazı toplamalar gerçekleştirme desenini ifade eder. Bu makalede, bir fan-in/fan-out senaryosu uygulamak için Dayanıklı İşlevler kullanan bir örnek açıklanmaktadır. Örnek, bir uygulamanın site içeriğinin tamamını veya bir kısmını Azure Depolama'ya yedekleyen dayanıklı bir işlevdir.

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 ile 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.

Önkoşullar

Senaryoya genel bakış

Bu örnekte, işlevler belirtilen bir dizin altındaki tüm dosyaları yinelenen olarak blob depolamaya yükler. Ayrıca karşıya yüklenen toplam bayt sayısını da sayarlar.

Her şeyi halleden tek bir işlev yazmak mümkündür. Karşılaşacağınız temel sorun ölçeklenebilirliktir. Tek bir işlev yürütmesi yalnızca tek bir sanal makinede çalıştırılabilir, bu nedenle aktarım hızı bu tek VM'nin aktarım hızıyla sınırlandırılır. Bir diğer sorun da güvenilirliktir. İşlemin ortasında bir hata varsa veya işlemin tamamı 5 dakikadan uzun sürüyorsa yedekleme kısmen tamamlanmış durumda başarısız olabilir. Daha sonra yeniden başlatılması gerekir.

İki normal işlev yazmak daha sağlam bir yaklaşım olacaktır: biri dosyaları numaralandırır, dosya adlarını kuyruğa ekler ve diğeri kuyruktan okuyup dosyaları blob depolamaya yükler. Bu yaklaşım aktarım hızı ve güvenilirlik açısından daha iyidir, ancak kuyruk sağlamanızı ve yönetmenizi gerektirir. Daha da önemlisi, karşıya yüklenen toplam bayt sayısını raporlama gibi daha fazlasını yapmak istiyorsanız , durum yönetimi ve koordinasyon açısından önemli bir karmaşıklık ortaya konur.

Dayanıklı İşlevler bir yaklaşım, çok düşük ek yük ile bahsedilen avantajların tümünü sunar.

İşlevler

Bu makalede örnek uygulamada aşağıdaki işlevler açıklanmaktadır:

  • E2_BackupSiteContent: Yedeklene dosyaların listesini almak için çağıran E2_GetFileList ve ardından her dosyayı yedeklemeye çağıran E2_CopyFileToBlobbir düzenleyici işlevi.
  • E2_GetFileList: Dizindeki dosyaların listesini döndüren etkinlik işlevi .
  • E2_CopyFileToBlob: Tek bir dosyayı Azure Blob Depolama yedekleyen etkinlik işlevi.

orchestrator işlevini E2_BackupSiteContent

Bu düzenleyici işlevi temelde aşağıdakileri yapar:

  1. Giriş parametresi olarak bir rootDirectory değer alır.
  2. altında rootDirectorydosyaların özyinelemeli bir listesini almak için bir işlevi çağırır.
  3. Her dosyayı Azure Blob Depolama yüklemek için birden çok paralel işlev çağrısı yapar.
  4. Tüm karşıya yüklemelerin tamamlanmasını bekler.
  5. Azure Blob Depolama yüklenen toplam bayt sayısını döndürür.

Orchestrator işlevini uygulayan kod aşağıdadır:

[FunctionName("E2_BackupSiteContent")]
public static async Task<long> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext backupContext)
{
    string rootDirectory = backupContext.GetInput<string>()?.Trim();
    if (string.IsNullOrEmpty(rootDirectory))
    {
        rootDirectory = Directory.GetParent(typeof(BackupSiteContent).Assembly.Location).FullName;
    }

    string[] files = await backupContext.CallActivityAsync<string[]>(
        "E2_GetFileList",
        rootDirectory);

    var tasks = new Task<long>[files.Length];
    for (int i = 0; i < files.Length; i++)
    {
        tasks[i] = backupContext.CallActivityAsync<long>(
            "E2_CopyFileToBlob",
            files[i]);
    }

    await Task.WhenAll(tasks);

    long totalBytes = tasks.Sum(t => t.Result);
    return totalBytes;
}

Çizgiye await Task.WhenAll(tasks); dikkat edin. İşleve E2_CopyFileToBlob yapılan tek tek çağrılar beklenmedi ve bu da paralel olarak çalışmalarına olanak tanır. Bu görev dizisini 'ye Task.WhenAllgeçirdiğimizde , tüm kopyalama işlemleri tamamlanana kadar tamamlanmayacak bir görevi geri alacağız. .NET'teki Görev Paralel Kitaplığı'nı (TPL) biliyorsanız, bu sizin için yeni değildir. Aradaki fark, bu görevlerin aynı anda birden çok sanal makinede çalışıyor olması ve Dayanıklı İşlevler uzantısının uçtan uca yürütmenin geri dönüşümü işlemeye dayanıklı olmasını sağlamasıdır.

'den Task.WhenAllbekledikten sonra, tüm işlev çağrılarının tamamlandığını ve değerleri bize geri döndürdüğünü biliyoruz. her çağrısı E2_CopyFileToBlob karşıya yüklenen bayt sayısını döndürür, bu nedenle toplam bayt sayısını hesaplamak, tüm bu dönüş değerlerinin bir araya eklenmesiyle ilgili bir konudur.

Yardımcı etkinlik işlevleri

Yardımcı etkinlik işlevleri, diğer örneklerde olduğu gibi yalnızca tetikleyici bağlamasını activityTrigger kullanan normal işlevlerdir.

etkinlik işlevini E2_GetFileList

[FunctionName("E2_GetFileList")]
public static string[] GetFileList(
    [ActivityTrigger] string rootDirectory, 
    ILogger log)
{
    log.LogInformation($"Searching for files under '{rootDirectory}'...");
    string[] files = Directory.GetFiles(rootDirectory, "*", SearchOption.AllDirectories);
    log.LogInformation($"Found {files.Length} file(s) under {rootDirectory}.");

    return files;
}

Not

Bu kodu neden doğrudan orchestrator işlevine koyamadığınızı merak ediyor olabilirsiniz. Bunu yapabilirsiniz, ancak bu, düzenleyici işlevlerinin temel kurallarından birini bozar. Bu, yerel dosya sistemi erişimi de dahil olmak üzere hiçbir zaman G/Ç yapmaması gerektiğidir. Daha fazla bilgi için bkz . Orchestrator işlev kodu kısıtlamaları.

etkinlik işlevini E2_CopyFileToBlob

[FunctionName("E2_CopyFileToBlob")]
public static async Task<long> CopyFileToBlob(
    [ActivityTrigger] string filePath,
    Binder binder,
    ILogger log)
{
    long byteCount = new FileInfo(filePath).Length;

    // strip the drive letter prefix and convert to forward slashes
    string blobPath = filePath
        .Substring(Path.GetPathRoot(filePath).Length)
        .Replace('\\', '/');
    string outputLocation = $"backups/{blobPath}";

    log.LogInformation($"Copying '{filePath}' to '{outputLocation}'. Total bytes = {byteCount}.");

    // copy the file contents into a blob
    using (Stream source = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
    using (Stream destination = await binder.BindAsync<CloudBlobStream>(
        new BlobAttribute(outputLocation, FileAccess.Write)))
    {
        await source.CopyToAsync(destination);
    }

    return byteCount;
}

Not

Örnek kodu çalıştırmak için NuGet paketini yüklemeniz Microsoft.Azure.WebJobs.Extensions.Storage gerekir.

işlevi, Azure İşlevleri bağlamalarının bazı gelişmiş özelliklerini (parametrenin Binder kullanımı) kullanır, ancak bu kılavuzun amacı için bu ayrıntılar hakkında endişelenmeniz gerekmez.

Uygulama, dosyayı diskten yükler ve içeriği zaman uyumsuz olarak "yedeklemeler" kapsayıcısında aynı ada sahip bir bloba akışla aktarır. Dönüş değeri, depolama alanına kopyalanan bayt sayısıdır ve daha sonra düzenleyici işlevi tarafından toplam toplamı hesaplamak için kullanılır.

Not

Bu, G/Ç işlemlerini bir işleve taşımanın mükemmel bir activityTrigger örneğidir. Çalışma yalnızca birçok farklı makineye dağıtılamaz, aynı zamanda ilerleme durumunu kontrol etme avantajından da yararlanırsınız. Konak işlemi herhangi bir nedenle sonlandırılırsa, hangi yüklemelerin zaten tamamlandığını biliyorsunuz.

Örneği çalıştırma

Windows'da aşağıdaki HTTP POST isteğini göndererek düzenlemeyi başlatabilirsiniz.

POST http://{host}/orchestrators/E2_BackupSiteContent
Content-Type: application/json
Content-Length: 20

"D:\\home\\LogFiles"

Alternatif olarak, bir Linux İşlev Uygulamasında (Python şu anda yalnızca App Service için Linux üzerinde çalıştırılır) düzenlemeyi şu şekilde başlatabilirsiniz:

POST http://{host}/orchestrators/E2_BackupSiteContent
Content-Type: application/json
Content-Length: 20

"/home/site/wwwroot"

Not

HttpStart Çağırdığınız işlev yalnızca JSON biçimli içerikle çalışır. Bu nedenle üst Content-Type: application/json bilgi gereklidir ve dizin yolu bir JSON dizesi olarak kodlanmıştır. Ayrıca HTTP kod parçacığı, dosyada tüm HTTP tetikleyici işlevleri URL'lerinden host.json varsayılan api/ ön eki kaldıran bir giriş olduğunu varsayar. Bu yapılandırma için işaretlemeyi örneklerdeki host.json dosyada bulabilirsiniz.

Bu HTTP isteği orchestrator'ı E2_BackupSiteContent tetikler ve dizeyi D:\home\LogFiles parametre olarak geçirir. Yanıt, yedekleme işleminin durumunu almak için bir bağlantı sağlar:

HTTP/1.1 202 Accepted
Content-Length: 719
Content-Type: application/json; charset=utf-8
Location: http://{host}/runtime/webhooks/durabletask/instances/b4e9bdcc435d460f8dc008115ff0a8a9?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}

(...trimmed...)

İşlev uygulamanızda kaç günlük dosyası bulunduğuna bağlı olarak, bu işlemin tamamlanması birkaç dakika sürebilir. Önceki HTTP 202 yanıtının üst bilgisindeki URL'yi Location sorgulayarak en son durumu alabilirsiniz.

GET http://{host}/runtime/webhooks/durabletask/instances/b4e9bdcc435d460f8dc008115ff0a8a9?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
HTTP/1.1 202 Accepted
Content-Length: 148
Content-Type: application/json; charset=utf-8
Location: http://{host}/runtime/webhooks/durabletask/instances/b4e9bdcc435d460f8dc008115ff0a8a9?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}

{"runtimeStatus":"Running","input":"D:\\home\\LogFiles","output":null,"createdTime":"2019-06-29T18:50:55Z","lastUpdatedTime":"2019-06-29T18:51:16Z"}

Bu durumda işlev çalışmaya devam eder. Düzenleyici durumuna kaydedilen girişi ve son güncelleştirme zamanını görebilirsiniz. Tamamlanmasını sorgulamak için üst bilgi değerlerini kullanmaya Location devam edebilirsiniz. Durum "Tamamlandı" olduğunda, aşağıdakine benzer bir HTTP yanıt değeri görürsünüz:

HTTP/1.1 200 OK
Content-Length: 152
Content-Type: application/json; charset=utf-8

{"runtimeStatus":"Completed","input":"D:\\home\\LogFiles","output":452071,"createdTime":"2019-06-29T18:50:55Z","lastUpdatedTime":"2019-06-29T18:51:26Z"}

Artık düzenlemenin tamamlandığını ve tamamlanmasının yaklaşık ne kadar sürdüğünü görebilirsiniz. Ayrıca, alan için output yaklaşık 450 KB günlüklerin karşıya yüklendiğini gösteren bir değer görürsünüz.

Sonraki adımlar

Bu örnek, fan-out/fan-in deseninin nasıl uygulandığını göstermiştir. Sonraki örnekte , dayanıklı zamanlayıcılar kullanılarak izleyici deseninin nasıl uygulanacakları gösterilmektedir.