Dela via


Reliable Services-meddelanden

Meddelanden gör det möjligt för klienter att spåra de ändringar som görs i ett objekt som de är intresserade av. Två typer av objekt stöder meddelanden: Reliable State Manager och Reliable Dictionary.

Vanliga orsaker till att använda meddelanden är:

  • Skapa materialiserade vyer, till exempel sekundära index eller aggregerade filtrerade vyer av replikens tillstånd. Ett exempel är ett sorterat index för alla nycklar i Reliable Dictionary.
  • Skicka övervakningsdata, till exempel antalet användare som lagts till under den senaste timmen.

Meddelanden utlöses som en del av tillämpningsåtgärderna. På en primär replik tillämpas åtgärder efter kvorumbekräftelse som en del av transaction.CommitAsync() eller this.StateManager.GetOrAddAsync(). På sekundära repliker tillämpas åtgärder vid databearbetning i replikeringskö. Därför bör meddelanden hanteras så snabbt som möjligt och synkrona händelser bör inte innehålla några dyra åtgärder. Annars kan det påverka transaktionsbearbetningstiden negativt samt replikversioner.

Reliable State Manager-meddelanden

Reliable State Manager tillhandahåller meddelanden om följande händelser:

  • Transaktion
    • Checka in
  • Tillståndshanterare
    • Återskapa
    • Tillägg av ett tillförlitligt tillstånd
    • Borttagning av ett tillförlitligt tillstånd

Reliable State Manager spårar de aktuella inflight-transaktionerna. Den enda ändringen i transaktionstillståndet som gör att ett meddelande utlöses är en transaktion som checkas in.

Reliable State Manager har en samling tillförlitliga tillstånd som Reliable Dictionary och Reliable Queue. Reliable State Manager utlöser meddelanden när den här samlingen ändras: ett tillförlitligt tillstånd läggs till eller tas bort eller hela samlingen återskapas. Reliable State Manager-samlingen återskapas i tre fall:

  • Återställning: När en replik startar återställs dess tidigare tillstånd från disken. I slutet av återställningen använder den NotifyStateManagerChangedEventArgs för att utlösa en händelse som innehåller uppsättningen återställda tillförlitliga tillstånd.
  • Fullständig kopia: Innan en replik kan ansluta till konfigurationsuppsättningen måste den skapas. Ibland kräver detta att en fullständig kopia av Reliable State Manager-tillståndet från den primära repliken tillämpas på den inaktiva sekundära repliken. Reliable State Manager på den sekundära repliken använder NotifyStateManagerChangedEventArgs för att utlösa en händelse som innehåller uppsättningen tillförlitliga tillstånd som den hämtade från den primära repliken.
  • Återställning: I haveriberedskapsscenarier kan replikens tillstånd återställas från en säkerhetskopia via RestoreAsync. I sådana fall använder Reliable State Manager på den primära repliken NotifyStateManagerChangedEventArgs för att utlösa en händelse som innehåller uppsättningen tillförlitliga tillstånd som den återställde från säkerhetskopian.

Om du vill registrera dig för transaktionsaviseringar och/eller state manager-meddelanden måste du registrera dig för händelserna TransactionChanged eller StateManagerChanged på Reliable State Manager. En vanlig plats att registrera med dessa händelsehanterare är konstruktorn för din tillståndskänsliga tjänst. När du registrerar dig för konstruktorn missar du inte något meddelande som orsakas av en ändring under IReliableStateManagers livslängd.

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

Händelsehanteraren TransactionChanged använder NotifyTransactionChangedEventArgs för att ge information om händelsen. Den innehåller åtgärdsegenskapen (till exempel NotifyTransactionChangedAction.Commit) som anger typen av ändring. Den innehåller också den transaktionsegenskap som innehåller en referens till den transaktion som ändrades.

Kommentar

I dag utlöses TransactionChanged-händelser endast om transaktionen har checkats in. Åtgärden är sedan lika med NotifyTransactionChangedAction.Commit. Men i framtiden kan händelser genereras för andra typer av ändringar i transaktionstillståndet. Vi rekommenderar att du kontrollerar åtgärden och bearbetar händelsen endast om det är en som du förväntar dig.

Följande är ett exempel på en TransactionChanged-händelsehanterare .

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);
    }
}

Händelsehanteraren StateManagerChanged använder NotifyStateManagerChangedEventArgs för att ge information om händelsen. NotifyStateManagerChangedEventArgs har två underklasser: NotifyStateManagerRebuildEventArgs och NotifyStateManagerSingleEntityChangedEventArgs. Du använder åtgärdsegenskapen i NotifyStateManagerChangedEventArgs för att omvandla NotifyStateManagerChangedEventArgs till rätt underklass:

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

Följande är ett exempel på en StateManagerChanged-meddelandehanterare .

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

        return;
    }

    this.ProcessStateManagerSingleEntityNotification(e);
}

Reliable Dictionary-meddelanden

Reliable Dictionary innehåller meddelanden om följande händelser:

  • Återskapa: Anropas när ReliableDictionary har återställts till ett läsbart mellanliggande återställningstillstånd från ett återställt eller kopierat lokalt tillstånd eller en säkerhetskopia. En post med transaktioner sedan återställningstillståndet skapades tillämpas sedan innan ombyggnaden är klar. Programmet för den posten ger tydliga, lägga till, uppdatera och/eller ta bort meddelanden.
  • Rensa: Anropas när tillståndet reliabledictionary har rensats via metoden ClearAsync .
  • Lägg till: Anropas när ett objekt har lagts till i ReliableDictionary.
  • Uppdatering: Anropas när ett objekt i IReliableDictionary har uppdaterats.
  • Ta bort: Anropas när ett objekt i IReliableDictionary har tagits bort.

För att få reliable dictionary-meddelanden måste du registrera dig med Händelsehanteraren DictionaryChangedIReliableDictionary. En vanlig plats att registrera med dessa händelsehanterare finns i meddelandet ReliableStateManager.StateManagerChanged add. Om du registrerar när IReliableDictionary läggs till i IReliableStateManager ser du till att du inte missar några meddelanden.

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;
        }
    }
}

Kommentar

ProcessStateManagerSingleEntityNotification är exempelmetoden som föregående OnStateManagerChangedHandler-exempel anropar.

Föregående kod anger gränssnittet IReliableNotificationAsyncCallback tillsammans med DictionaryChanged. Eftersom NotifyDictionaryRebuildEventArgs innehåller ett IAsyncEnumerable-gränssnitt – som måste räknas upp asynkront – utlöses återskapningsmeddelanden via RebuildNotificationAsyncCallback i stället för 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);
    }
}

Kommentar

I föregående kod rensas först det underhållna aggregerade tillståndet som en del av bearbetningen av återskapningsmeddelandet. Eftersom den tillförlitliga samlingen återskapas med ett nytt tillstånd är alla tidigare meddelanden irrelevanta.

Händelsehanteraren DictionaryChanged använder NotifyDictionaryChangedEventArgs för att ge information om händelsen. NotifyDictionaryChangedEventArgs har fem underklasser. Använd åtgärdsegenskapen i NotifyDictionaryChangedEventArgs för att omvandla NotifyDictionaryChangedEventArgs till rätt underklass:

  • 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;
    }
}

Rekommendationer

  • Utför aviseringshändelser så snabbt som möjligt.
  • Kör inte några dyra åtgärder (till exempel I/O-åtgärder) som en del av synkrona händelser.
  • Kontrollera åtgärdstypen innan du bearbetar händelsen. Nya åtgärdstyper kan läggas till i framtiden.

Här följer några saker att tänka på:

  • Meddelanden utlöses som en del av körningen av en åtgärd. Till exempel utlöses ett återställningsmeddelande som ett steg i en återställningsåtgärd. En återställning fortsätter inte förrän meddelandehändelsen har bearbetats.
  • Eftersom meddelanden utlöses som en del av tillämpningsåtgärderna ser klienter endast meddelanden för lokalt engagerade åtgärder. Och eftersom åtgärder garanteras endast att vara lokalt engagerade (med andra ord loggade), kan de eller kanske inte ångras i framtiden.
  • På sökvägen gör om utlöses ett enda meddelande för varje tillämpad åtgärd. Det innebär att om transaktion T1 innehåller Create(X), Delete(X) och Create(X) får du ett meddelande om att X skapas, ett för borttagningen och ett för skapandet igen i den ordningen.
  • För transaktioner som innehåller flera åtgärder tillämpas åtgärderna i den ordning de togs emot på den primära repliken från användaren.
  • Som en del av bearbetningen av falska förlopp kan vissa åtgärder ångras på sekundära repliker. Meddelanden genereras för sådana ångra-åtgärder, vilket återställer replikens tillstånd till en stabil punkt. En viktig skillnad när det gäller att ångra meddelanden är att händelser som har dubblettnycklar aggregeras. Om t.ex. transaktion T1 ångras visas ett enda meddelande till Delete(X).

Nästa steg

Kända problem

  • I vissa situationer kan vissa transaktionsmeddelanden hoppas över under en återskapande. I det här fallet är rätt värde fortfarande närvarande och kan fortfarande läsas eller itereras. endast meddelandet saknas. För att återställa minnesinternt tillstånd använder tillförlitliga samlingar en logg för framåtskrivning som regelbundet komprimeras till en kontrollpunktsfil. Under återställningen läses först bastillståndet in från kontrollpunktsfiler som utlöser ett återskapningsmeddelande. Sedan tillämpas transaktionerna som sparas i loggen, var och en utlöser ett eget meddelande om att rensa, lägga till, uppdatera eller ta bort. Det här problemet kan uppstå från ett konkurrenstillstånd där en ny kontrollpunkt tas snabbt efter en återställning. Om kontrollpunkten slutförs före loggens program anges tillståndet för den nya kontrollpunkten i minnestillståndet. Även om detta resulterar i rätt tillstånd innebär det att transaktioner i loggen som ännu inte har tillämpats inte skickar meddelanden.