Dayanıklı varlıklar

Varlık işlevleri, dayanıklı varlıklar olarak adlandırılan küçük durum parçalarını okuyan ve güncelleştiren işlemleri tanımlar. Orchestrator işlevleri gibi varlık işlevleri de varlık tetikleyicisi olarak adlandırılan özel bir tetikleyici türü kullanır. Orchestrator işlevlerinden farklı olarak varlık işlevleri, denetim akışı aracılığıyla durumu göstermek yerine varlık durumunu açıkça yönetir. Varlıklar, her birinin durumu mütevazı olan birçok varlık arasında iş dağıtarak uygulamaların ölçeğini genişletmenize yardımcı olur.

Varlıklar, dayanıklı varlıklar olarak adlandırılan küçük durum parçalarını okuyan ve güncelleştiren işlemleri tanımlar. Varlıklar, orkestratörlerden farklı olarak durumu denetim akışı yoluyla temsil etmek yerine açıkça yönetir. Varlıklar, her birinin durumu mütevazı olan birçok varlık arasında iş dağıtarak uygulamaların ölçeğini genişletmenize yardımcı olur.

Dayanıklı varlıklar için destek

Varlık işlevleri ve ilgili özellikler Dayanıklı İşlevler 2.0 ve sonraki sürümlerde kullanılabilir.

Programlama dili Dayanıklı varlıklar için destek
.NET yalıtılmış
.NET süreç içi
Java
Python
JavaScript
PowerShell
Dayanıklı Görev SDK'sı Dayanıklı varlıklar için destek
.NET yalıtılmış
.NET süreç içi
Java
Python
JavaScript
PowerShell

Dayanıklı varlıklar için genel kavramlar

Varlıklar, iletileri kullanarak iletişim kuran küçük hizmetler gibi davranır. Her varlığın benzersiz bir kimliği ve gerekirse iç durumu vardır. Varlıklar istendiğinde işlemleri çalıştırır. İşlem durumu güncelleştirebilir, dış hizmetleri çağırabilir veya yanıt bekleyebilir. Varlıklar, çalışma zamanında güvenilir kuyruklar aracılığıyla gönderilen iletiler aracılığıyla diğer varlıklarla, orkestrasyonlar ve istemcilerle iletişim kurar.

Çakışmaları önlemek için, tek bir varlık işlemleri ardı ardına seri olarak çalıştırır.

Uyarı

Bir varlığı tetiklediğinizde, yükü tamamlayana kadar işler, ardından yeni bir giriş geldiğinde devreye giren yeni bir yürütmeyi planlar. Sonuç olarak, varlık yürütme günlükleriniz her çağrıdan sonra ek bir yürütme gösterebilir. Bu beklenen bir durum.

Varlık Kimliği

Bir varlığa erişmek için varlık kimliğini kullanın. Varlık kimliği, bir varlık örneğini benzersiz olarak tanımlayan dize çiftidir. Şunlardan oluşur:

  • Varlık türünü tanımlayan varlık adı. Örneğin, Counter. Bu ad, varlığı uygulayan varlık işlevinin adıyla eşleşir. Büyük/küçük harfe duyarlı değildir.
  • Varlık anahtarı, varlığı aynı ada sahip diğer tüm varlıklar arasında benzersiz olarak tanımlar. Örneğin, bir GUID (Evrensel Benzersiz Tanımlayıcı).

Örneğin, çevrimiçi bir oyunda puan tutmak için bir Counter varlık işlevi kullanılabilir. Oyunun her örneği, @Counter@Game1 ve @Counter@Game2 gibi benzersiz bir varlık kimliğine sahiptir. Bir varlığı hedeflemek için varlık kimliğini belirtin.

Varlık işlemleri

Bir varlıkta bir işlemi çağırmak için şunları belirtin:

  • Hedef varlığın Varlık Kimliği.
  • gerçekleştirilecek işlemi belirten bir dize olan işlem adı. Örneğin, Counter varlık add, get veya reset işlemlerini destekleyebilir.
  • İşlem girişi, işlem için isteğe bağlı bir parametredir. Örneğin, add işlem giriş olarak bir tamsayı tutar alır.
  • İşlemin teslim süresini belirtmek için isteğe bağlı bir parametre olan zamanlanmış saat. Örneğin, bir işlemi birkaç gün sonra çalışacak şekilde zamanlayın.

İşlemler javascript hatası veya .NET özel durumu gibi bir sonuç değeri veya hata sonucu döndürebilir. Çağrı orkestrasyonu sonucu veya hatayı alır.

İşlemler, .NET özel durumu veya Python özel durumu gibi bir sonuç değeri veya hata sonucu döndürebilir. Çağıran sonucu veya hatayı alır.

Varlık işlemi ayrıca varlığın durumunu oluşturabilir, okuyabilir, güncelleştirebilir ve silebilir. Çalışma zamanı her zaman varlık durumunu depolamada saklar.

Varlıkları tanımlama

.NET'da varlıkları tanımlamak için iki API'lerden birini kullanın:

İşlev tabanlı söz dizimi: İşlev tabanlı söz diziminde, her varlığı bir işlev olarak yazar ve uygulamanızda işlem dağıtırsınız. Bu söz dizimi, uygulama çerçevelerinde olduğu gibi basit durumu, birkaç işlemi veya dinamik bir işlem kümesi olan varlıklar için iyi çalışır. Ancak derleme zamanında tür hatalarını yakalamadığından bakımı yorucu olabilir.

Sınıf tabanlı söz dizimi: .NET sınıfları ve yöntemleri, varlıkları ve işlemleri modellemektedir. Bu söz dizimi kodun okunmasını kolaylaştırır ve işlemleri güvenli bir şekilde türe çağırmanızı sağlar. İşlev tabanlı söz diziminin üzerinde ince bir katman olduğundan, aynı uygulamada her iki değişkeni de karıştırabilirsiniz.

Kullandığınız API'ler, C# işlevlerinizin nerede çalıştığına bağlıdır. Yalıtılmış bir çalışan işlemi önerilir, ancak ana süreçte de çalıştırabilirsiniz.

İşlem içi işlev tabanlı örnek:

Bu örnekte dayanıklı işlev olarak uygulanan basit Counter bir varlık gösterilmektedir. Tamsayı durumu kullanan üç işlemi tanımlar:addreset ve get.

[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
    switch (ctx.OperationName.ToLowerInvariant())
    {
        case "add":
            ctx.SetState(ctx.GetState<int>() + ctx.GetInput<int>());
            break;
        case "reset":
            ctx.SetState(0);
            break;
        case "get":
            ctx.Return(ctx.GetState<int>());
            break;
    }
}

Daha fazla bilgi için bkz. İşlev tabanlı söz dizimi.


İşlem içi sınıf tabanlı örnek:

Bu örnekte sınıflar ve yöntemler kullanılarak uygulanan varlığın aynısı Counter gösterilmektedir.

[JsonObject(MemberSerialization.OptIn)]
public class Counter
{
    [JsonProperty("value")]
    public int CurrentValue { get; set; }

    public void Add(int amount) => this.CurrentValue += amount;

    public void Reset() => this.CurrentValue = 0;

    public int Get() => this.CurrentValue;

    [FunctionName(nameof(Counter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
        => ctx.DispatchAsync<Counter>();
}

Bu varlık, geçerli sayaç değerini tutan bir Counter nesnede durumu depolar. Dayanıklı İşlevler Json.NET kitaplığını kullanarak bu nesneyi serileştirir ve seri durumdan çıkartır.

Daha fazla bilgi için bkz. Varlık sınıflarını tanımlama.


Yalıtılmış çalışan süreç işlev tabanlı örnek:

Aşağıdaki örnekte, yalıtılmış bir çalışan işleminde işlev tabanlı Counter bir varlık gösterilmektedir. add, reset, get ve delete'ü destekler.

[Function(nameof(Counter))]
public static Task Counter([EntityTrigger] TaskEntityDispatcher dispatcher)
{
    return dispatcher.DispatchAsync(operation =>
    {
        if (operation.State.GetState(typeof(int)) is null)
        {
            operation.State.SetState(0);
        }

        switch (operation.Name.ToLowerInvariant())
        {
            case "add":
                int state = operation.State.GetState<int>();
                state += operation.GetInput<int>();
                operation.State.SetState(state);
                return new(state);
            case "reset":
                operation.State.SetState(0);
                break;
            case "get":
                return new(operation.State.GetState<int>());
            case "delete":
                operation.State.SetState(null);
                break;
        }

        return default;
    });
}

Yalıtılmış işçi işlemi sınıf tabanlı örnek:

Aşağıdaki örnekte sınıfları ve yöntemleri kullanarak varlığın Counter uygulanması gösterilmektedir.

public class Counter : TaskEntity<int>
{
    readonly ILogger logger;

    public Counter(ILogger<Counter> logger)
    {
        this.logger = logger;
    }

    public void Add(int amount) => this.State += amount;

    public void Reset() => this.State = 0;

    public int Get() => this.State;

    [Function(nameof(Counter))]
    public Task RunEntityAsync([EntityTrigger] TaskEntityDispatcher dispatcher)
    {
        return dispatcher.DispatchAsync(this);
    }
}

.NET için Dayanıklı Görev SDK'sı, sınıf tabanlı söz dizimi kullanarak varlıkların tanımlanmasını destekler. Varlığınızı tanımlamak için temel sınıfı uygulayabilirsiniz TaskEntity<TState> .

Aşağıdaki örnekte Dayanıklı Görev SDK'sı kullanılarak uygulanan bir Counter varlık gösterilmektedir:

using Microsoft.DurableTask.Entities;

public class Counter : TaskEntity<int>
{
    public void Add(int amount) => this.State += amount;

    public void Reset() => this.State = 0;

    public int Get() => this.State;
}

Varlığı çalışanla kaydetmek için:

builder.Services.AddDurableTaskWorker()
    .AddTasks(registry =>
    {
        registry.AddEntity<Counter>();
    })
    .UseDurableTaskScheduler(connectionString);

Bir orkestratörden bir varlığa sinyal vermek veya çağırmak için:

public class EntityOrchestration : TaskOrchestrator<string, int>
{
    public override async Task<int> RunAsync(TaskOrchestrationContext context, string entityKey)
    {
        var entityId = new EntityInstanceId(nameof(Counter), entityKey);

        // Signal the entity (fire-and-forget)
        await context.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);

        // Call the entity and wait for response
        int currentValue = await context.Entities.CallEntityAsync<int>(entityId, nameof(Counter.Get));

        return currentValue;
    }
}

Nesnelere erişim

Tek yönlü veya iki yönlü iletişim kullanarak varlıklara erişin:

  • Bir varlığı çağırmak iki yönlü (gidiş dönüş) iletişim kullanır. Varlığa bir işlem iletisi gönderin ve devam etmeden önce yanıt iletisini bekleyin. Yanıt iletisi bir sonuç değeri veya hata (örneğin, JavaScript hatası veya .NET özel durumu) sağlar.
  • Sinyalleme, bir bileşenin tek yönlü (fire and forget) iletişim kullanması anlamına gelir. İşlem iletisi gönderin, ancak yanıt beklemeyin. Çalışma zamanı teslimi garanti eder, ancak gönderen sonuç değerlerini veya hatalarını gözlemleyemez.

İstemci işlevlerinden, orkestratör işlevlerinden veya varlık işlevlerinden varlıklara erişin. Her bağlam her iki iletişim türünü de desteklemez:

  • İstemci işlevleri varlıklara sinyal sağlamayı ve varlık durumunu okumayı destekler.
  • Orkestratör işlevleri, varlıkların sinyallemesini ve çağrılmasını destekler.
  • Varlık işlevleri, varlıkların sinyallerini destekler.

Tek yönlü veya iki yönlü iletişim kullanarak varlıklara erişin:

  • Bir varlığı çağırmak iki yönlü (gidiş dönüş) iletişim kullanır. Varlığa bir işlem iletisi gönderin ve devam etmeden önce yanıt iletisini bekleyin. Yanıt iletisi bir sonuç değeri veya hata sağlar.
  • Sinyalleme, bir bileşenin tek yönlü (fire and forget) iletişim kullanması anlamına gelir. İşlem iletisi gönderin, ancak yanıt beklemeyin. Çalışma zamanı teslimi garanti eder, ancak gönderen sonuç değerlerini veya hatalarını gözlemleyemez.

İstemcilerden veya düzenleyicilerden varlıklara erişin. Her bağlam her iki iletişim türünü de desteklemez:

  • İstemciler, entitelerin sinyalleşmesini ve entite durumunun okunmasını destekler.
  • Orkestra yöneticileri, bileşenlerin sinyallerini ve çağrılarını destekler.

Aşağıdaki örneklerde varlıklara erişim gösterilmektedir.

Örnek: istemci bir varlığa sinyal gönderir

İstemci işlevi olarak da bilinen sıradan bir Azure İşlevinden varlıklara erişmek için entity istemci bağlamasını kullanın. Aşağıdaki örnekte, bu bağlamayı kullanarak bir varlığa işaret eden kuyrukla tetiklenen bir işlev gösterilmektedir.

Uyarı

Kolaylık olması için, aşağıdaki örneklerde varlıklara erişmek için gevşek yazılan söz dizimi gösterilmektedir. Genel olarak, daha fazla tür denetimi sağladığından varlıklara arabirimler aracılığıyla erişin .

Devam eden işlem:

Devam eden işlem:

[FunctionName("AddFromQueue")]
public static Task Run(
    [QueueTrigger("durable-function-trigger")] string input,
    [DurableClient] IDurableEntityClient client)
{
    // Entity operation input comes from the queue message content.
    var entityId = new EntityId(nameof(Counter), "myCounter");
    int amount = int.Parse(input);
    return client.SignalEntityAsync(entityId, "Add", amount);
}

Yalıtılmış çalışan işlemi:

[Function("AddFromQueue")]
public static Task Run(
    [QueueTrigger("durable-function-trigger")] string input,
    [DurableClient] DurableTaskClient client)
{
    // Entity operation input comes from the queue message content.
    var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
    int amount = int.Parse(input);
    return client.Entities.SignalEntityAsync(entityId, "Add", amount);
}

Sinyal terimi, varlık API çağrısının tek yönlü ve zaman uyumsuz olduğu anlamına gelir. İstemci işlevi, varlığın işlemi ne zaman gerçekleştirdiğini bilemez. İstemci işlevi sonuç değerlerini veya özel durumları gözlemleyemez.

Bir istemciden varlıklara erişmek için varlık durumunu belirtmek veya okumak amacıyla DurableTaskClient kullanın.

// Signal an entity
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
await client.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);

Sinyal terimi, varlık API çağrısının tek yönlü ve zaman uyumsuz olduğu anlamına gelir. İstemci, birimin işlemi tam olarak ne zaman gerçekleştirdiğini bilemez.

Örnek: istemci varlık durumunu okur

İstemci işlevinden varlık durumunu sorgulama:

Devam eden işlem:

[FunctionName("QueryCounter")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req,
    [DurableClient] IDurableEntityClient client)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");
    EntityStateResponse<JObject> stateResponse = await client.ReadEntityStateAsync<JObject>(entityId);
    return req.CreateResponse(HttpStatusCode.OK, stateResponse.EntityState);
}

Yalıtılmış çalışan işlemi:

[Function("QueryCounter")]
public static async Task<HttpResponseData> Run(
    [HttpTrigger(AuthorizationLevel.Function)] HttpRequestData req,
    [DurableClient] DurableTaskClient client)
{
    var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
    EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);

    if (entity is null)
    {
        return req.CreateResponse(HttpStatusCode.NotFound);
    }

    HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
    await response.WriteAsJsonAsync(entity);

    return response;
}

İstemciler bir varlığın durumunu sorgulayabilir:

var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);

if (entity != null)
{
    Console.WriteLine($"Current value: {entity.State}");
}

Varlık durumu sorguları dayanıklı izleme deposuna gönderilir ve varlığın en son kalıcı durumunu döndürür. Bu durum her zaman "taahhüt edilen" bir durumdur, yani hiçbir zaman bir işlemi yürütmenin ortasında geçici bir ara durum değildir. Ancak bu durum varlığın bellek içi durumuyla karşılaştırıldığında eski olabilir. Aşağıdaki bölümde açıklandığı gibi yalnızca düzenleme işlemleri bir varlığın bellek içi durumunu okuyabilir.

Örnek: orkestrasyon sinyalleri gönderir ve bir varlığı çağırır

Orchestrator işlevleri, düzenleme tetikleyicisi bağlaması üzerindeki API'leri kullanarak varlıklara erişebilir. Aşağıdaki örnek kod, bir varlığı çağıran ve işaretleyen bir Counter orchestrator işlevini gösterir.

Devam eden işlem:

[FunctionName("CounterOrchestration")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");

    // Two-way call to the entity which returns a value - awaits the response
    int currentValue = await context.CallEntityAsync<int>(entityId, "Get");
    if (currentValue < 10)
    {
        // One-way signal to the entity which updates the value - does not await a response
        context.SignalEntity(entityId, "Add", 1);
    }
}

Yalıtılmış çalışan işlemi:

[Function("CounterOrchestration")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
    var entityId = new EntityInstanceId(nameof(Counter), "myCounter");

    // Two-way call to the entity which returns a value - awaits the response
    int currentValue = await context.Entities.CallEntityAsync<int>(entityId, "Get");

    if (currentValue < 10)
    {
        // One-way signal to the entity which updates the value - does not await a response
        await context.Entities.SignalEntityAsync(entityId, "Add", 1);
    }
}

Yalnızca orkestrasyonlar varlıkları çağırabilir ve bir yanıt alabilir; bu bir dönüş değeri veya özel durum olabilir. İstemci bağlamasını kullanan istemci işlevleri yalnızca varlıklara sinyal verebilir.

Düzenleyiciler, bağlamın Varlıklar API'sini kullanarak varlıklara erişebilir:

public class CounterOrchestration : TaskOrchestrator<string, int>
{
    public override async Task<int> RunAsync(TaskOrchestrationContext context, string entityKey)
    {
        var entityId = new EntityInstanceId(nameof(Counter), entityKey);

        // Two-way call to the entity which returns a value - awaits the response
        int currentValue = await context.Entities.CallEntityAsync<int>(entityId, nameof(Counter.Get));

        if (currentValue < 10)
        {
            // One-way signal to the entity - does not await a response
            await context.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);
        }

        return currentValue;
    }
}

Yalnızca orkestratörler varlıkları çağırabilir ve yanıt alabilir; bu bir dönüş değeri veya özel durum olabilir. Müşteriler yalnızca varlıklara sinyal verebilir.

Uyarı

Bir düzenleyiciden bir varlığı çağırmak, etkinliği çağırmaya benzer. Temel fark, varlıkların bir adrese (varlık kimliği) sahip dayanıklı nesneler olması ve işlem adı belirtmeyi desteklemesidir. Etkinlikler durumsuzdur ve işlem kavramına sahip değildir.

Örnek: varlık bir varlığın sinyallerini veriyor

Varlık işlevi, bir işlemi yürütürken diğer varlıklara veya hatta kendisine sinyal gönderebilir. Örneğin, sayaç 100'e ulaştığında bir izleyici varlığına "kilometre taşına ulaşıldı" sinyali göndermek için önceki Counter varlık örneğini değiştirin.

Devam eden işlem:

   case "add":
        var currentValue = ctx.GetState<int>();
        var amount = ctx.GetInput<int>();
        if (currentValue < 100 && currentValue + amount >= 100)
        {
            ctx.SignalEntity(new EntityId("MonitorEntity", ""), "milestone-reached", ctx.EntityKey);
        }

        ctx.SetState(currentValue + amount);
        break;

Yalıtılmış çalışan işlemi:

case "add":
    var currentValue = operation.State.GetState<int>();
    var amount = operation.GetInput<int>();
    if (currentValue < 100 && currentValue + amount >= 100)
    {
        operation.Context.SignalEntity(new EntityInstanceId("MonitorEntity", ""), "milestone-reached", operation.Context.EntityInstanceId);
    }

    operation.State.SetState(currentValue + amount);
    break;

Varlık koordinasyonu

Bazen işlemleri birden çok varlık arasında koordine etmeniz gerekir. Örneğin, bir bankacılık uygulamasında varlıklar bireysel banka hesaplarını temsil edebilir. Bir hesaptan diğerine fon aktardığınızda, kaynak hesabın yeterli fona sahip olduğundan emin olmanız gerekir. Ayrıca her iki hesabı da tek bir tutarlı işlem olarak güncelleştirmeniz gerekir.

Örnek: Fon aktarma (C#)

Aşağıdaki örnek kod, bir orchestrator işlevi kullanarak iki hesap varlığı arasında fon aktarır. Varlık güncelleştirmelerini koordine etmek için LockAsync yöntemini kullanarak orkestrasyonda kritik bölüm oluşturun.

Uyarı

Kolaylık olması için, bu örnekte daha önce tanımlanan varlık yeniden kullanılır Counter . Gerçek bir uygulamada daha ayrıntılı BankAccount bir varlık tanımlamak daha iyidir.

// This is a method called by an orchestrator function
public static async Task<bool> TransferFundsAsync(
    string sourceId,
    string destinationId,
    int transferAmount,
    IDurableOrchestrationContext context)
{
    var sourceEntity = new EntityId(nameof(Counter), sourceId);
    var destinationEntity = new EntityId(nameof(Counter), destinationId);

    // Create a critical section to avoid race conditions.
    // No operations can be performed on either the source or
    // destination accounts until the locks are released.
    using (await context.LockAsync(sourceEntity, destinationEntity))
    {
        ICounter sourceProxy =
            context.CreateEntityProxy<ICounter>(sourceEntity);
        ICounter destinationProxy =
            context.CreateEntityProxy<ICounter>(destinationEntity);

        int sourceBalance = await sourceProxy.Get();

        if (sourceBalance >= transferAmount)
        {
            await sourceProxy.Add(-transferAmount);
            await destinationProxy.Add(transferAmount);

            // the transfer succeeded
            return true;
        }
        else
        {
            // the transfer failed due to insufficient funds
            return false;
        }
    }
}

.NET'te LockAsync, IDisposable döndürür. Bu bölümün atılması kritik bölümü sonlandırır. Kritik bölümü temsil etmek için bunu bir using blokla kullanın.

Yukarıdaki örnekte, bir düzenleyici işlevi kaynak varlıktan hedef varlığa fon aktarır. yöntemi hem LockAsync kaynak hem de hedef hesap varlıklarını kilitledi. Bu kilitleme, düzenleme mantığının using ifadesinin sonundaki kritik bölümden çıkana kadar başka hiçbir istemcinin iki hesaptan birinin durumunu sorgulayamaması veya değiştirememesi için garanti sağladı. Bu davranış, kaynak hesapta overdraft'ları önler.

Uyarı

Düzenleme normalde veya hatayla sona erdiğinde, devam eden tüm kritik bölümler örtük olarak sona erer ve sistem tüm kilitleri serbest bırakır.

Kritik bölüm davranışı

LockAsync yöntemi bir orkestrasyonda kritik bir bölüm oluşturur. Bu kritik bölümler, diğer düzenlemelerin belirli bir varlık kümesinde çakışan değişiklikler yapmasını engeller. API dahili olarak varlıklara LockAsync "kilit" işlemleri gönderir ve her varlıktan bir "kilit alındı" yanıtı aldıktan sonra döndürür. Hem kilit hem de kilit açma, tüm varlıklar tarafından desteklenen yerleşik işlemlerdir.

Diğer istemciler, bir varlık kilitliyken varlık üzerinde işlem çalıştıramaz. Bu davranış, bir varlığın aynı anda yalnızca tek bir orkestrasyon örneği tarafından kilitlenebilmesini sağlar. Bir çağıran, bir orkestrasyon tarafından kilitlenmiş bir varlıkta bir işlemi gerçekleştirmeye çalışırsa, bu işlem bekleyen işlemler kuyruğuna yerleştirilir. Bağlayan orkestrasyon kilidini serbest bırakana kadar bekleyen işlemler işlenmez.

Uyarı

Bu davranış, C# deyimi gibi lock çoğu programlama dilinde kullanılan eşitleme temel öğelerinden biraz farklıdır. Örneğin, C# dilinde tüm iş parçacıklarının düzgün bir eşitlemeyi sağlamak için lock deyimini kullanması gerekir. Ancak, varlıklar tüm çağıranların bir varlığı açıkça kilitlemesini zorunlu kılmaz. Çağıran herhangi biri bir varlığı kilitlerse, bu varlık üzerindeki diğer tüm işlemler engellenir ve bu kilidin arkasında kuyruğa alınır.

Varlıklardaki kilitler daimidir, bu nedenle yürütme işlemi tekrar başlatılsa bile kalıcı olur. Sistem, bir varlığın kalıcı durumu kapsamında kilitleri kalıcı olarak saklar.

İşlemlerden farklı olarak, kritik bölümler hatalar oluştuğunda değişiklikleri otomatik olarak geri almaz. Bunun yerine, geri alma veya yeniden deneme gibi bir hata işleme yazın, örneğin hataları veya istisnaları yakalayarak. Bu tasarım seçimi kasıtlıdır. Orkestrasyonların etkinlikler çalıştırması ve geri alınamaz dış hizmetlere çağrılar yapması nedeniyle, bir orkestrasyonun tüm etkilerini otomatik olarak geri almak zor veya genelde imkansızdır. Ayrıca, geri alma girişimleri başarısız olabilir ve daha fazla hata işleme gerektirebilir.

Kritik bölüm kuralları

Çoğu programlama dilindeki düşük düzeyli kilitleme temel öğelerinin aksine kritik bölümlerin kilitlenmemesi garanti edilir. Kilitlenmeleri önlemek için aşağıdaki kısıtlamaları uygularız:

  • Kritik bölümler iç içe yerleştirilemiyor.
  • Kritik bölümler alt orkestrasyonlar oluşturamaz.
  • Kritik bölümler yalnızca kilitledikleri varlıkları çağırabilir.
  • Kritik bölümler birden çok paralel çağrı kullanarak aynı varlığı çağıramaz.
  • Kritik bölümler yalnızca kilit kümesinin dışındaki varlıklara sinyal verebilir.

Bu kuralların ihlal edilmesi, .NET LockingRulesViolationException gibi bir çalışma zamanı hatasına neden olur ve hangi kuralın bozulduğunu açıklayan bir ileti içerir.

Dayanıklı varlıkların sanal aktörlerle karşılaştırılması

Dayanıklı varlıklar aktör modelinden birçok fikir kullanır. Aktörler hakkında bilgi sahibiyseniz, bu makaledeki çeşitli kavramları tanıyabilirsiniz. Dayanıklı varlıklar Orleans projesindeki tahıllar olarak da adlandırılan sanal aktörlere benzer. Örneğin:

  • Varlık kimliği kullanarak dayanıklı varlıkları ele alırsınız.
  • Yarış koşullarını önlemek amacıyla dayanıklı varlık işlemleri seri olarak çalıştırılır.
  • Bir varlığı çağırmak veya bu varlığın sinyallerini almak, varlığı örtük olarak oluşturur.
  • Çalışma zamanı, işlemler çalıştırılmadığında varlıkları bellekten kaldırır.

Önemli farklar şunlardır:

  • Dayanıklı varlıklar gecikme süresine göre dayanıklılığı önceliklendirir, bu nedenle katı gecikme süresi gereksinimlerine sahip uygulamalara uymayabilir.
  • Dayanıklı varlıklar, iletilerin zaman aşımına uğramasına neden olmaz. Orleans, yapılandırılabilir bir süreden (varsayılan olarak 30 saniye) sonra iletileri zaman aşımına uğratır.
  • Varlıklar mesajları güvenilir bir şekilde ve sırayla iletir. Orleans, akış mesajları için güvenilir, siparişli teslimi destekler, ancak tahıllar arasındaki tüm mesajlar için garanti vermez.
  • Orchestrations, varlıklarla istek yanıtını kullanabileceğiniz tek yerdir. Bir varlığın içinde, özgün aktör modelinde olduğu gibi tek yönlü mesajlaşma (sinyal) kullanın.
  • Dayanıklı varlıklar kilitlenmez. Orleans çıkmaza girer ve iletiler zaman aşımına uyana kadar kilitlenmeler devam eder.
  • Dayanıklı varlıklar dayanıklı düzenlemelerle çalışır ve dağıtılmış kilitleme mekanizmalarını destekler.

Sonraki Adımlar