Aracılığıyla paylaş


Zamanlayıcılar ve anımsatıcılar

Çalışma Orleans zamanı, geliştiricinin dilimler için düzenli davranış belirtmesini sağlayan zamanlayıcılar ve anımsatıcılar olarak adlandırılan iki mekanizma sağlar.

Süreölçerler

Zamanlayıcılar , birden çok etkinleştirmeyi (tanenin örneklemeleri) yaymak için gerekli olmayan düzenli dilim davranışı oluşturmak için kullanılır. Zamanlayıcı, standart .NET System.Threading.Timer sınıfıyla aynıdır. Buna ek olarak, zamanlayıcılar, çalıştıkları iş birimi içinde tek iş parçacıklı yürütme garantilerine tabidir.

Her etkinleştirmeyle ilişkili sıfır veya daha fazla zamanlayıcı olabilir. Çalışma zamanı, ilişkili olduğu etkinleştirmenin çalışma zamanı bağlamında her zamanlayıcı yordamını yürütür.

Zamanlayıcı kullanımı

Zamanlayıcı başlatmak için bir başvuru döndüren RegisterGrainTimer yöntemini kullanınIGrainTimer:

protected IGrainTimer RegisterGrainTimer<TState>(
    Func<TState, CancellationToken, Task> callback, // function invoked when the timer ticks
    TState state,                                   // object to pass to callback
    GrainTimerCreationOptions options)              // timer creation options

Zamanlayıcıyı iptal etmek için atacaksınız.

Tahıl devre dışı bırakılırsa veya bir hata oluştuğunda ve silo kilitlendiğinde zamanlayıcı tetiklenmez.

Önemli noktalar:

  • Etkinleştirme koleksiyonu etkinleştirildiğinde, bir zamanlayıcı geri çağırmasının yürütülmesi, etkinleştirmenin boştaki durumunu kullanımda olarak değiştirmez. Bu, zamanlayıcının, aksi takdirde boşta etkinleştirmelerin devre dışı bırakılabilmesini ertelemek için kullanılamayacağı anlamına gelir.
  • geçirilen Grain.RegisterGrainTimer süre, tarafından döndürülenin Task çözümlenme anından callback sonraki çağrının gerçekleşmesi gereken ana kadar geçen süredircallback. Bu, ardışık çağrıların çakışmasını callback imkansız hale getirmekle kalmaz, aynı zamanda tamamlanması için gereken sürenin callback çağrılma callback sıklığını etkilemesini de sağlar. Bu, semantiğinden önemli bir sapmadır System.Threading.Timer.
  • Her çağrısı callback ayrı bir dönüşte bir etkinleştirmeye teslim edilir ve aynı etkinleştirmeyi açan diğer turnelerle hiçbir zaman eşzamanlı olarak çalıştırilmez.
  • Geri çağırmalar varsayılan olarak araya alınmaz. Araya ekleme özelliği GrainTimerCreationOptions üzerinde Interleave ayarı true olarak ayarlanarak etkinleştirilebilir.
  • Grain zamanlayıcıları, döndürülen IGrainTimer örneğindeki Change(TimeSpan, TimeSpan) yöntemi kullanılarak güncelleştirilebilir.
  • Geri çağırmalar, zamanlayıcı süresinin görece kısa olması durumunda toplanmasına engel olarak tahılı etkin tutabilir. GrainTimerCreationOptions üzerinde KeepAlive değeri true olarak ayarlanarak etkinleştirilebilir.
  • Geri çağırmalar, zamanlayıcı nesnesi imha edildiğinde veya "grain" devre dışı bırakılmaya başladığında iptal edilen bir CancellationToken alabilir.
  • Geri çağırmalar, onları tetikleyen zamanlayıcıyı sonlandırabilir.
  • Geri çağırmalar, ayrıntılı çağrı filtrelerine tabidir.
  • Dağıtılmış izleme etkinleştirildiğinde, geri çağırmalar dağıtılmış izlemede görünür.
  • POCO tanecikleri (Grain'dan devralmayan tanecik sınıfları), RegisterGrainTimer uzantısı yöntemini kullanarak taneli zamanlayıcıları kaydedebilir.

Anımsatıcılar

Anımsatıcılar zamanlayıcılara benzer ve birkaç önemli fark vardır:

  • Anımsatıcılar kalıcıdır ve açıkça iptal edilmediği sürece neredeyse tüm durumlarda (kısmi veya tam küme yeniden başlatmaları dahil) tetiklenmeye devam eder.
  • Anımsatıcı "tanımları" depolama alanına yazılır. Ancak belirli bir oluşum, belirli bir zamana sahip değildir. Bu, küme belirli bir anımsatıcı onay işareti sırasında devre dışı kalırsa yanıtsız bırakılacağı ve anımsatıcının yalnızca bir sonraki onay işaretinin gerçekleşeceği yan etkisine sahiptir.
  • Anımsatıcılar belirli bir etkinleştirmeyle değil, bir tanecikle ilişkilendirilir.
  • Bir tahılın, bir anımsatıcı değer geçtiğinde bununla ilişkili bir etkinleştirmesi yoksa, tane oluşturulur. Etkinleştirme boşta kalırsa ve devre dışı bırakılırsa, aynı taneyle ilişkili bir anımsatıcı, sonraki adımlarda dilimi yeniden etkinleştirir.
  • Anımsatıcı teslimi ileti yoluyla gerçekleşir ve diğer tüm tahıl yöntemleriyle aynı araya ekleme semantiğine tabidir.
  • Anımsatıcılar yüksek frekanslı zamanlayıcılar için kullanılmamalıdır; süreleri dakika, saat veya gün cinsinden ölçülmelidir.

Yapılandırma

Anımsatıcılar, kalıcı olarak çalışması için depolamaya dayanır. Anımsatıcı alt sistemi işlevinden önce hangi depolama yedeklemesinin kullanılacağını belirtmelisiniz. Bu işlem, uzantı yöntemleri aracılığıyla Use{X}ReminderService anımsatıcı sağlayıcılarından birini yapılandırarak yapılır; burada X sağlayıcının adıdır, örneğin, UseAzureTableReminderService.

Azure Tablo yapılandırması:

// TODO replace with your connection string
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new HostBuilder()
    .UseOrleans(builder =>
    {
        builder.UseAzureTableReminderService(connectionString)
    })
    .Build();

SQL:

const string connectionString = "YOUR_CONNECTION_STRING_HERE";
const string invariant = "YOUR_INVARIANT";
var silo = new HostBuilder()
    .UseOrleans(builder =>
    {
        builder.UseAdoNetReminderService(options =>
        {
            options.ConnectionString = connectionString; // Redacted
            options.Invariant = invariant;
        });
    })
    .Build();

Yalnızca bir Azure hesabı veya SQL veritabanı ayarlamanıza gerek kalmadan anımsatıcıların yer tutucu uygulamasının çalışmasını istiyorsanız, bu size anımsatıcı sisteminin yalnızca geliştirme amaçlı bir uygulamasını sağlar:

var silo = new HostBuilder()
    .UseOrleans(builder =>
    {
        builder.UseInMemoryReminderService();
    })
    .Build();

Önemli

Siloların farklı tanecik türlerini işlediği (farklı arabirimler uyguladığı) heterojen bir kümeniz varsa, silonun kendisi anımsatıcıları işlemese bile her silo Anımsatıcılar yapılandırmasını eklemelidir.

Anımsatıcı kullanımı

Anımsatıcıları kullanan bir tanecik yöntemini uygulamalıdır IRemindable.ReceiveReminder .

Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
{
    Console.WriteLine("Thanks for reminding me-- I almost forgot!");
    return Task.CompletedTask;
}

Anımsatıcı başlatmak için nesnesini döndüren Grain.RegisterOrUpdateReminder yöntemini kullanınIGrainReminder:

protected Task<IGrainReminder> RegisterOrUpdateReminder(
    string reminderName,
    TimeSpan dueTime,
    TimeSpan period)
  • reminderName: bağlamsal dilim kapsamında anımsatıcıyı benzersiz olarak tanımlaması gereken bir dizedir.
  • dueTime: ilk zamanlayıcı onay işaretini vermeden önce beklenmesi gereken süreyi belirtir.
  • period: zamanlayıcının süresini belirtir.

Anımsatıcılar tek bir etkinleştirmenin ömrü boyunca devam ettiğinden, açıkça iptal edilmelidir (atılmak yerine). Öğesini çağırarak Grain.UnregisterReminderbir anımsatıcıyı iptal edebilirsiniz:

protected Task UnregisterReminder(IGrainReminder reminder)

tarafından reminder döndürülen Grain.RegisterOrUpdateRemindertanıtıcı nesnesidir.

örneklerinin IGrainReminder , etkinleştirme süresinden daha uzun bir zaman boyunca geçerli olacağı garanti edilmemektedir. Anımsatıcıyı kalıcı bir şekilde tanımlamak istiyorsanız, anımsatıcının adını içeren bir dize kullanın.

Yalnızca anımsatıcının adına sahipseniz ve buna karşılık gelen örneğine IGrainReminderihtiyacınız varsa yöntemini çağırın Grain.GetReminder :

protected Task<IGrainReminder> GetReminder(string reminderName)

Hangisinin kullanılacağına karar verme

Aşağıdaki durumlarda zamanlayıcıları kullanmanızı öneririz:

  • Etkinleştirme devre dışı bırakıldığında veya hatalar oluştuğunda zamanlayıcının çalışmaması önemli değilse (veya istenirse).
  • Zamanlayıcının çözünürlüğü küçüktür (örneğin, saniye veya dakika cinsinden makul bir şekilde ifade edilebilir).
  • Zamanlayıcı geri çağırması, bir taneli yöntem çağrıldığında veya uygulamasından Grain.OnActivateAsync() başlatılabilir.

Aşağıdaki durumlarda anımsatıcıları kullanmanızı öneririz:

  • Düzenli davranışın etkinleştirmeden ve herhangi bir hatadan kurtulması gerektiğinde.
  • Seyrek görevler gerçekleştirme (örneğin, dakika, saat veya gün cinsinden makul bir şekilde ifade edilebilir).

Zamanlayıcıları ve anımsatıcıları birleştirme

Hedefinize ulaşmak için anımsatıcılar ve zamanlayıcıların bir bileşimini kullanmayı düşünebilirsiniz. Örneğin, etkinleştirmeler arasında hayatta kalması gereken küçük bir çözünürlüğe sahip bir zamanlayıcıya ihtiyacınız varsa, amacı devre dışı bırakma nedeniyle kaybolmuş olabilecek yerel zamanlayıcıyı yeniden başlatan bir dilimi uyandırmak olan beş dakikada bir çalışan bir anımsatıcı kullanabilirsiniz.

POCO tane kayıtları

PoCO dilimine zamanlayıcı veya anımsatıcı kaydetmek için arabirimini uygular IGrainBase ve veya ITimerRegistry öğesini tahılın oluşturucusuna eklersinizIReminderRegistry.

using Orleans.Timers;

namespace Timers;

public sealed class PingGrain : IGrainBase, IPingGrain, IDisposable
{
    private const string ReminderName = "ExampleReminder";

    private readonly IReminderRegistry _reminderRegistry;

    private IGrainReminder? _reminder;

    public  IGrainContext GrainContext { get; }

    public PingGrain(
        ITimerRegistry timerRegistry,
        IReminderRegistry reminderRegistry,
        IGrainContext grainContext)
    {
        // Register timer
        timerRegistry.RegisterGrainTimer(
            grainContext,
            callback: static async (state, cancellationToken) =>
            {
                // Omitted for brevity...
                // Use state

                await Task.CompletedTask;
            },
            state: this,
            options: new GrainTimerCreationOptions
            {
                DueTime = TimeSpan.FromSeconds(3),
                Period = TimeSpan.FromSeconds(10)
            });

        _reminderRegistry = reminderRegistry;

        GrainContext = grainContext;
    }

    public async Task Ping()
    {
        _reminder = await _reminderRegistry.RegisterOrUpdateReminder(
            callingGrainId: GrainContext.GrainId,
            reminderName: ReminderName,
            dueTime: TimeSpan.Zero,
            period: TimeSpan.FromHours(1));
    }

    void IDisposable.Dispose()
    {
        if (_reminder is not null)
        {
            _reminderRegistry.UnregisterReminder(
                GrainContext.GrainId, _reminder);
        }
    }
}

Yukarıdaki kod:

  • , IGrainBaseve IPingGrainuygulayan IDisposablebir POCO dilimi tanımlar.
  • Her 10 saniyede bir çağrılan ve kayıttan 3 saniye sonra başlayan bir zamanlayıcı kaydeder.
  • Çağrıldığında Ping , saatte bir çağrılan bir anımsatıcı kaydeder ve kayıttan hemen sonra başlar.
  • yöntemi, Dispose kayıtlıysa anımsatıcıyı iptal eder.