Aracılığıyla paylaş


Gözlemciler

Bazen basit bir ileti/yanıt deseni yeterli olmaz ve istemcinin zaman uyumsuz bildirimler alması gerekir. Örneğin, bir kullanıcı bir arkadaşı yeni bir anlık ileti yayımladığında bildirim almak isteyebilir.

İstemci gözlemcileri, istemcilere eşzamansız bildirim yapılmasına olanak tanıyan bir mekanizmadır. Gözlemci arabirimlerinin öğesinden IGrainObserverdevralması ve tüm yöntemlerin , , voidTask, Task<TResult>veya ValueTaskdöndürmesi ValueTask<TResult>gerekir. void'yi uygulamada teşvik edebileceği için async void dönüş türünü önermiyoruz. Yöntemden bir özel durum atılırsa uygulamanın kilitlenmesine neden olabileceği için bu tehlikeli bir desendir. Bunun yerine, en iyi efor bildirim senaryoları için gözlemcinin arabirim yöntemine uygulamayı OneWayAttribute göz önünde bulundurun. Bu, alıcının yöntem çağrısı için yanıt göndermemesini sağlar ve yöntemin gözlemciden yanıt beklemeden hemen çağrı sitesinde döndürülmesini sağlar. Bir tanecik, herhangi bir taneli arabirim yöntemi gibi çağırarak bir gözlemci üzerinde bir yöntem çağırır. Çalışma Orleans zamanı, isteklerin ve yanıtların teslim edilmesini sağlar. Gözlemciler için yaygın bir kullanım örneği, uygulamada bir olay gerçekleştiğinde bildirim almak üzere bir istemciyi listelemektir Orleans . Bu tür bildirimlerin ayrıntılı olarak yayımlanması, gözlemci eklemek veya kaldırmak için bir API sağlamalıdır. Ayrıca, mevcut aboneliğin iptaline izin veren bir yöntemi kullanıma sunma genellikle uygundur.

Gözlemlenen tanecik türlerinin geliştirilmesini basitleştirmek için gibi ObserverManager<TObserver> bir yardımcı program sınıfı kullanabilirsiniz. Hatadan sonra gerektiğinde otomatik olarak yeniden etkinleştirilen Orleans taneciklerden farklı olarak, istemciler hataya dayanıklı değildir: başarısız olan bir istemci asla kurtarılamayabilir. Bu nedenle yardımcı program, ObserverManager<T> yapılandırılan süre sonunda abonelikleri kaldırır. Etkin istemcilerin aboneliklerini etkin tutmak için zamanlayıcıya yeniden abone olmaları gerekir.

Bir bildirime abone olmak için istemcinin önce gözlemci arabirimini uygulayan bir yerel nesne oluşturması gerekir. Daha sonra nesneyi bir tahıl referansına dönüştürmek için tahıl fabrikasında CreateObjectReference yöntemini çağırır. Daha sonra bu referansı bildirim yapan taneciğin abonelik yöntemine geçirebilirsiniz.

Diğer tahıllar da zaman uyumsuz bildirimler almak için bu modeli kullanabilir. Bileşenler IGrainObserver arabirimlerini uygulayabilir. İstemci aboneliği durumundan farklı olarak, abone olan tanecik yalnızca gözlemci arabirimini uygular ve kendisinin bir referansını iletir (örneğin, this.AsReference<IMyGrainObserverInterface>()). Tahıllar zaten adreslenebilir olduğundan buna gerek CreateObjectReference yoktur.

Kod örneği

İstemcilere düzenli aralıklarla ileti gönderen bir diliminiz olduğunu varsayalım. Kolaylık olması için örneğimizdeki ileti bir dizedir. İlk olarak, istemcide iletiyi alan arabirimi tanımlayın.

Arabirim şöyle görünür:

public interface IChat : IGrainObserver
{
    Task ReceiveMessage(string message);
}

Tek özel gereksinim, arabirimin IGrainObserver'den devralması gerektiğidir. Şimdi, bu iletileri gözlemlemek isteyen tüm istemciler IChatuygulayan bir sınıf uygulamalıdır.

En basit örnek şöyle görünür:

public class Chat : IChat
{
    public Task ReceiveMessage(string message)
    {
        Console.WriteLine(message);
        return Task.CompletedTask;
    }
}

Sunucuda, bir sonraki adımda bu sohbet iletilerini istemcilere gönderen bir biriminiz olmalıdır. Ayrıca, grain istemcilerin bildirimlere abone olması ve abonelikten çıkmaları için bir mekanizma sağlamalıdır. Abonelikler için grain, ObserverManager<IChat> yardımcı programı sınıfının bir örneğini kullanabilir.

Uyarı

ObserverManager<TObserver> sürüm 7.0'ın bir parçasıdır Orleans . Eski sürümler için aşağıdaki uygulama kopyalanabilir.

class HelloGrain : Grain, IHello
{
    private readonly ObserverManager<IChat> _subsManager;

    public HelloGrain(ILogger<HelloGrain> logger)
    {
        _subsManager =
            new ObserverManager<IChat>(
                TimeSpan.FromMinutes(5), logger);
    }

    // Clients call this to subscribe.
    public Task Subscribe(IChat observer)
    {
        _subsManager.Subscribe(observer, observer);

        return Task.CompletedTask;
    }

    //Clients use this to unsubscribe and no longer receive messages.
    public Task UnSubscribe(IChat observer)
    {
        _subsManager.Unsubscribe(observer);

        return Task.CompletedTask;
    }
}

İstemcilere ileti göndermek için Notify örneğinin yöntemini kullanın<. Yöntem, bir Action<T> yöntem veya lambda ifadesi alır (burada T, IChat türündedir). Arabirimdeki herhangi bir yöntemi çağırarak istemcilere gönderebilirsiniz. Bizim örneğimizde tek bir yöntemimiz ReceiveMessagevardır ve sunucudaki gönderme kodumuz şu şekilde görünür:

public Task SendUpdateMessage(string message)
{
    _subsManager.Notify(s => s.ReceiveMessage(message));

    return Task.CompletedTask;
}

Sunucumuzda gözlemci istemcilere ileti gönderme yöntemi ve abone olmak/abonelikten çıkmak için iki yöntem vardır. İstemci, tahıl iletilerini gözlemleyebilecek bir sınıf uyguladı. Son adım, daha önce uyguladığımız Chat sınıfı kullanarak istemcide bir gözlemci başvurusu oluşturmak ve abone olduktan sonra ileti almasına izin vermektir.

Kod şöyle görünür:

//First create the grain reference
var friend = _grainFactory.GetGrain<IHello>(0);
Chat c = new Chat();

//Create a reference for chat, usable for subscribing to the observable grain.
var obj = _grainFactory.CreateObjectReference<IChat>(c);

//Subscribe the instance to receive messages.
await friend.Subscribe(obj);

Sunucumuzdaki grain SendUpdateMessage yöntemini her çağırdığında, abone olan tüm istemciler iletiyi alır. İstemci kodumuzda değişkendeki Chatc örnek iletiyi alır ve konsola gönderir.

Önemli

Objeler CreateObjectReference'ye WeakReference<T> ile tutulur ve bu nedenle başka bir referans yoksa çöp toplanır.

Toplanmasını istemediğiniz her gözlemci için bir referans tutmanız gerekir.

Uyarı

Gözlemci barındıran bir istemci başarısız olabileceği ve kurtarmadan sonra oluşturulan gözlemcilerin farklı (rastgele) kimlikleri olduğundan gözlemciler doğal olarak güvenilir değildir. ObserverManager<TObserver>, etkin olmayan gözlemcileri kaldırabilmek için yukarıda açıklandığı üzere gözlemcilerin düzenli olarak yeniden abone olmalarına dayanır.

Yürütme modeli

uygulamaları IGrainObserver çağrısıyla IGrainFactory.CreateObjectReferencekaydedilir. Bu yönteme yapılan her çağrı, bu uygulamaya işaret eden yeni bir referans oluşturur. Orleans bu referansların her birine gönderilen istekleri sırayla, tamamlanana kadar yürütür. Gözlemciler yeniden girişli değildir; bu nedenle, Orleans eşzamanlı istekleri bir gözlemciye ayırmaz. Birden çok gözlemci eşzamanlı olarak istek alırsa, bu istekler paralel olarak yürütülebilir. gibi AlwaysInterleaveAttribute veya ReentrantAttribute gibi öznitelikler gözlemci yöntemlerinin yürütülmesini etkilemez; yürütme modelini özelleştiremezsiniz.

CancellationToken desteği

Orleans 9.0'dan itibaren gözlemci arabirim yöntemleri CancellationToken parametrelerini tam olarak destekler. Bu, tahılların gözlemcilere iptal sinyali vermesine olanak tanıyarak uzun süre çalışan gözlemci işlemlerinin düzgün bir şekilde durdurulmasına olanak tanır.

CancellationToken ile gözlemci arabirimi tanımlama

Gözlemci arabirim yönteminizde son parametre olarak bir CancellationToken parametre ekleyin:

public interface IDataObserver : IGrainObserver
{
    Task OnDataReceivedAsync(DataPayload data, CancellationToken cancellationToken = default);
}

gözlemciyi iptal desteğiyle uygulama

public class DataObserver : IDataObserver
{
    public async Task OnDataReceivedAsync(DataPayload data, CancellationToken cancellationToken = default)
    {
        // Check cancellation before processing
        cancellationToken.ThrowIfCancellationRequested();

        // Process data with cancellation-aware operations
        await ProcessDataAsync(data, cancellationToken);
    }

    private async Task ProcessDataAsync(DataPayload data, CancellationToken cancellationToken)
    {
        // Use cancellation token with async operations
        await Task.Delay(100, cancellationToken);
        Console.WriteLine($"Processed: {data.Id}");
    }
}

Gözlemcileri iptalle bilgilendirin

Gözlemcileri bilgilendirirken, işbirliğine dayalı iptali etkinleştirmek için bir iptal belirteci geçirebilirsiniz:

public async Task SendDataToObserversAsync(DataPayload data, CancellationToken cancellationToken = default)
{
    // Create a linked token source to combine the grain's token with a timeout
    using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
    cts.CancelAfter(TimeSpan.FromSeconds(30)); // Timeout for observer notifications

    await _subsManager.NotifyAsync(
        observer => observer.OnDataReceivedAsync(data, cts.Token));
}

tr-TR: Daha fazla bilgi için Orleans içinde iptal belirteçlerini kullanma hakkında Tahıllarda Orleans iptal belirteçlerini kullanma bölümüne bakınız.

Gözlemciler için CancellationToken desteği 9.0'da Orleans tanıtıldı. Önceki sürümler için geçici çözüm olarak kullanabilirsiniz GrainCancellationToken , ancak gözlemci yöntemlerinde doğrudan CancellationToken destek kullanılamaz.

Tam CancellationToken desteği için 9.0 veya sonraki bir sürüme Orleans yükseltmeyi göz önünde bulundurun.

Gözlemciler için CancellationToken desteği 9.0 ve üzeri sürümlerde Orleans kullanılabilir. Orleans 3.x, iptal için eski GrainCancellationToken mekanizmayı kullanır.