Sdílet prostřednictvím


Oznámení Reliable Services

Oznámení umožňují klientům sledovat změny provedené u objektu, který je zajímá. Dvě typy objektů podporují oznámení: Reliable State Manager a Reliable Dictionary.

Mezi běžné důvody použití oznámení patří:

  • Vytváření materializovaných zobrazení, jako jsou sekundární indexy nebo agregovaná filtrovaná zobrazení stavu repliky. Příkladem je seřazený index všech klíčů ve Reliable Dictionary.
  • Odesílání dat monitorování, například počet uživatelů přidaných za poslední hodinu

Oznámení se aktivují jako součást použití operací. V primární replice se operace použijí po potvrzení kvora jako součást transaction.CommitAsync() nebo this.StateManager.GetOrAddAsync(). Na sekundárních replikách se operace použijí při zpracování dat fronty replikace. Z tohoto důvodu by se oznámení měla zpracovávat co nejrychleji a synchronní události by neměly zahrnovat žádné nákladné operace. Jinak může mít negativní vliv na dobu zpracování transakcí a také na sestavení repliky.

Oznámení Reliable State Manageru

Reliable State Manager poskytuje oznámení pro následující události:

  • Transakce
    • Potvrzení
  • Správce stavů
    • Opětovné sestavení (Rebuild)
    • Přidání spolehlivého stavu
    • Odebrání spolehlivého stavu

Reliable State Manager sleduje aktuální příchozí transakce. Jedinou změnou ve stavu transakce, která způsobí, že se aktivuje oznámení, je transakce, která se potvrdí.

Reliable State Manager udržuje kolekci spolehlivých stavů, jako je Reliable Dictionary a Reliable Queue. Správce spolehlivého stavu aktivuje oznámení, když se tato kolekce změní: přidá nebo odebere spolehlivý stav nebo se znovu sestaví celá kolekce. Kolekce Reliable State Manager se znovu sestaví ve třech případech:

  • Obnovení: Při spuštění repliky obnoví předchozí stav z disku. Na konci obnovení používá NotifyStateManagerChangedEventArgs k aktivaci události, která obsahuje sadu obnovených spolehlivých stavů.
  • Úplná kopie: Před tím, než se replika může připojit ke konfigurační sadě, musí být sestavena. Někdy to vyžaduje, aby se na nečinnou sekundární repliku použila úplná kopie stavu Správce spolehlivého stavu z primární repliky. Správce spolehlivého stavu na sekundární replice používá NotifyStateManagerChangedEventArgs k aktivaci události, která obsahuje sadu spolehlivých stavů, které získala z primární repliky.
  • Obnovení: Ve scénářích zotavení po havárii je možné obnovit stav repliky ze zálohy prostřednictvím funkce RestoreAsync. V takových případech správce Reliable State Manager na primární replice používá NotifyStateManagerChangedEventArgs k aktivaci události, která obsahuje sadu spolehlivých stavů, které se obnovily ze zálohy.

Pokud chcete zaregistrovat oznámení o transakcích nebo oznámení správce stavu, musíte se zaregistrovat u událostí TransactionChanged nebo StateManagerChanged ve Správci spolehlivého stavu. Běžným místem pro registraci u těchto obslužných rutin událostí je konstruktor stavové služby. Když se zaregistrujete v konstruktoru, nezmeškáte žádné oznámení, které je způsobeno změnou během životnosti IReliableStateManager.

public MyService(StatefulServiceContext context)
    : base(MyService.EndpointName, context, CreateReliableStateManager(context))
{
    this.StateManager.TransactionChanged += this.OnTransactionChangedHandler;
    this.StateManager.StateManagerChanged += this.OnStateManagerChangedHandler;
}

Obslužná rutina události TransactionChangedEventArgs používá NotifyTransactionChangedEventArgs k poskytnutí podrobností o události. Obsahuje vlastnost akce (například NotifyTransactionChangedAction.Commit), která určuje typ změny. Obsahuje také vlastnost transakce, která poskytuje odkaz na transakci, která se změnila.

Poznámka:

Dnes jsou události TransactionChanged vyvolány pouze v případě, že transakce je potvrzena. Akce se pak rovná NotifyTransactionChangedAction.Commit. V budoucnu však mohou být události vyvolány pro jiné typy změn stavu transakce. Doporučujeme zkontrolovat akci a zpracovat událost jenom v případě, že ji očekáváte.

Následuje příklad TransactionChanged obslužné rutiny události.

private void OnTransactionChangedHandler(object sender, NotifyTransactionChangedEventArgs e)
{
    if (e.Action == NotifyTransactionChangedAction.Commit)
    {
        this.lastCommitLsn = e.Transaction.CommitSequenceNumber;
        this.lastTransactionId = e.Transaction.TransactionId;

        this.lastCommittedTransactionList.Add(e.Transaction.TransactionId);
    }
}

Obslužná rutina událostí StateManagerChangedEventArgs používá NotifyStateManagerChangedEventArgs k zadání podrobností o události. NotifyStateManagerChangedEventArgs má dvě podtřídy: NotifyStateManagerRebuildEventArgs a NotifyStateManagerSingleEntityChangedEventArgs. Vlastnost akce v NotifyStateManagerChangedEventArgs použijete k přetypování NotifyStateManagerChangedEventArgs na správnou podtřídu:

  • NotifyStateManagerChangedAction.Rebuild: NotifyStateManagerRebuildEventArgs
  • NotifyStateManagerChangedAction.Add and NotifyStateManagerChangedAction.Remove: NotifyStateManagerSingleEntityChangedEventArgs

Následuje příklad obslužné rutiny oznámení StateManagerChanged .

public void OnStateManagerChangedHandler(object sender, NotifyStateManagerChangedEventArgs e)
{
    if (e.Action == NotifyStateManagerChangedAction.Rebuild)
    {
        this.ProcessStateManagerRebuildNotification(e);

        return;
    }

    this.ProcessStateManagerSingleEntityNotification(e);
}

Spolehlivá oznámení slovníku

Reliable Dictionary poskytuje oznámení pro následující události:

  • Opětovné sestavení: Volá se, když se ReliableDictionary obnovil do čitelného zprostředkujícího stavu obnovení z obnoveného nebo zkopírovaného místního stavu nebo zálohy. Záznam transakcí od vytvoření tohoto stavu obnovení se pak použije před dokončením opětovného sestavení. Aplikace tohoto záznamu poskytne jasná oznámení, přidá, aktualizuje nebo odebere.
  • Clear: Volá se, když byl stav ReliableDictionary vymazán prostřednictvím ClearAsync metody.
  • Přidat: Volá se, když byla položka přidána do ReliableDictionary.
  • Aktualizace: Volá se při aktualizaci položky v IReliableDictionary .
  • Odebrat: Volá se, když byla odstraněna položka v IReliableDictionary .

Pokud chcete získat oznámení Reliable Dictionary, musíte se zaregistrovat u obslužné rutiny události DictionaryChanged v IReliableDictionary. Běžným místem pro registraci u těchto obslužných rutin událostí je přidání oznámení ReliableStateManager.StateManagerChanged . Registrace při přidání IReliableDictionary do IReliableStateManager zajistí, že vám nebudou chybět žádná oznámení.

private void ProcessStateManagerSingleEntityNotification(NotifyStateManagerChangedEventArgs e)
{
    var operation = e as NotifyStateManagerSingleEntityChangedEventArgs;

    if (operation.Action == NotifyStateManagerChangedAction.Add)
    {
        if (operation.ReliableState is IReliableDictionary<TKey, TValue>)
        {
            var dictionary = (IReliableDictionary<TKey, TValue>)operation.ReliableState;
            dictionary.RebuildNotificationAsyncCallback = this.OnDictionaryRebuildNotificationHandlerAsync;
            dictionary.DictionaryChanged += this.OnDictionaryChangedHandler;
        }
    }
}

Poznámka:

ProcessStateManagerSingleEntityNotification je ukázková metoda, kterou předchozí OnStateManagerChangedHandler příklad volá.

Předchozí kód nastaví IReliableNotificationAsyncCallback rozhraní spolu se DictionaryChanged. Vzhledem k tomu , že NotifyDictionaryRebuildEventArgs obsahuje rozhraní IAsyncEnumerable – které je potřeba vytvořit výčet asynchronně – oznámení o opětovném sestavení se aktivují prostřednictvím RebuildNotificationAsyncCallback místo OnDictionaryChangedHandler.

public async Task OnDictionaryRebuildNotificationHandlerAsync(
    IReliableDictionary<TKey, TValue> origin,
    NotifyDictionaryRebuildEventArgs<TKey, TValue> rebuildNotification)
{
    this.secondaryIndex.Clear();

    var enumerator = e.State.GetAsyncEnumerator();
    while (await enumerator.MoveNextAsync(CancellationToken.None))
    {
        this.secondaryIndex.Add(enumerator.Current.Key, enumerator.Current.Value);
    }
}

Poznámka:

V předchozím kódu v rámci zpracování oznámení o opětovném sestavení se nejprve vymaže udržovaný agregovaný stav. Vzhledem k tomu, že se spolehlivá kolekce znovu sestavuje s novým stavem, jsou všechna předchozí oznámení irelevantní.

Obslužná rutina události DictionaryChangedEventArgs používá NotifyDictionaryChangedEventArgs k zadání podrobností o události. NotifyDictionaryChangedEventArgs má pět podtříd. Pomocí vlastnosti akce NotifyDictionaryChangedEventArgs přetypujte NotifyDictionaryChangedEventArgs na správnou podtřídu:

  • NotifyDictionaryChangedAction.Rebuild: NotifyDictionaryRebuildEventArgs
  • NotifyDictionaryChangedAction.Clear: NotifyDictionaryClearEventArgs
  • NotifyDictionaryChangedAction.Add: NotifyDictionaryItemAddedEventArgs
  • NotifyDictionaryChangedAction.Update: NotifyDictionaryItemUpdatedEventArgs
  • NotifyDictionaryChangedAction.Remove: NotifyDictionaryItemRemovedEventArgs
public void OnDictionaryChangedHandler(object sender, NotifyDictionaryChangedEventArgs<TKey, TValue> e)
{
    switch (e.Action)
    {
        case NotifyDictionaryChangedAction.Clear:
            var clearEvent = e as NotifyDictionaryClearEventArgs<TKey, TValue>;
            this.ProcessClearNotification(clearEvent);
            return;

        case NotifyDictionaryChangedAction.Add:
            var addEvent = e as NotifyDictionaryItemAddedEventArgs<TKey, TValue>;
            this.ProcessAddNotification(addEvent);
            return;

        case NotifyDictionaryChangedAction.Update:
            var updateEvent = e as NotifyDictionaryItemUpdatedEventArgs<TKey, TValue>;
            this.ProcessUpdateNotification(updateEvent);
            return;

        case NotifyDictionaryChangedAction.Remove:
            var deleteEvent = e as NotifyDictionaryItemRemovedEventArgs<TKey, TValue>;
            this.ProcessRemoveNotification(deleteEvent);
            return;

        default:
            break;
    }
}

Doporučení

  • Co nejrychleji proveďte události oznámení.
  • V rámci synchronních událostí nespouštět žádné nákladné operace (například vstupně-výstupní operace).
  • Před procesem události zkontrolujte typ akce. V budoucnu se můžou přidat nové typy akcí.

Tady je několik věcí, které je potřeba mít na paměti:

  • Oznámení se aktivují jako součást provádění operace. Oznámení o obnovení se například aktivuje jako krok operace obnovení. Obnovení nebude pokračovat, dokud se nezpracuje událost oznámení.
  • Vzhledem k tomu, že se oznámení aktivují jako součást operací použití, klienti uvidí jenom oznámení pro místně potvrzené operace. A protože operace jsou zaručené pouze místně potvrzené (jinými slovy, protokolované), můžou nebo nemusí být v budoucnu vráceny zpět.
  • V cestě znovu se pro každou použitou operaci aktivuje jedno oznámení. To znamená, že pokud transakce T1 obsahuje Create(X), Delete(X) a Create(X), dostanete jedno oznámení o vytvoření X, jeden pro odstranění a druhý pro vytvoření znovu v tomto pořadí.
  • U transakcí, které obsahují více operací, se operace použijí v pořadí, v jakém byly přijaty na primární replice od uživatele.
  • V rámci zpracování nepravdivého průběhu mohou být některé operace na sekundárních replikách vráceny zpět. U takových operací vrácení zpět jsou vyvolána oznámení a stav repliky se vrátí do stabilního bodu. Jedním z důležitých rozdílů v oznámeních o vrácení zpět je agregace událostí s duplicitními klíči. Pokud je například transakce T1 vrácena zpět, zobrazí se jedno oznámení pro odstranění (X).

Další kroky

Známé problémy

  • V určitých situacích se během opětovného sestavení můžou některá oznámení o transakcích přeskočit. V tomto případě je správná hodnota stále přítomna a je stále možné ji číst nebo iterated; Chybí pouze oznámení. K obnovení stavu v paměti používají spolehlivé kolekce protokol s předstihem zápisu, který se pravidelně kondenzuje do souboru kontrolního bodu. Během obnovení se nejprve načte základní stav ze souborů kontrolních bodů, které aktivují oznámení o opětovném sestavení. Pak se použijí transakce uložené v protokolu, přičemž každá z nich aktivuje vlastní jasné oznámení, přidá, aktualizuje nebo odebere. K tomuto problému může dojít z konfliktu časování, kdy se po obnovení rychle provede nový kontrolní bod. Pokud se kontrolní bod dokončí před aplikací protokolu, stav v paměti se nastaví na stav nového kontrolního bodu. Výsledkem je správný stav, ale znamená to, že transakce v protokolu, které ještě nebyly použity, neodesílají oznámení.