Powiadomienia usługi Reliable Services

Powiadomienia umożliwiają klientom śledzenie zmian wprowadzonych w obiekcie, który cię interesuje. Dwa typy obiektów obsługują powiadomienia: Reliable State Manager i Reliable Dictionary.

Typowe przyczyny korzystania z powiadomień to:

  • Kompilowanie zmaterializowanych widoków, takich jak indeksy pomocnicze lub zagregowane przefiltrowane widoki stanu repliki. Przykładem jest posortowany indeks wszystkich kluczy w słowniku Reliable.
  • Wysyłanie danych monitorowania, takich jak liczba użytkowników dodanych w ciągu ostatniej godziny.

Powiadomienia są wyzwalane w ramach stosowania operacji. W repliki podstawowej operacje są stosowane po potwierdzeniu transaction.CommitAsync() kworum jako części lub this.StateManager.GetOrAddAsync(). W przypadku replik pomocniczych operacje są stosowane podczas przetwarzania danych kolejki replikacji. W związku z tym powiadomienia powinny być obsługiwane tak szybko, jak to możliwe, a zdarzenia synchroniczne nie powinny obejmować żadnych kosztownych operacji. W przeciwnym razie może to negatywnie wpłynąć na czas przetwarzania transakcji, a także kompilacje replik.

Powiadomienia usługi Reliable State Manager

Usługa Reliable State Manager udostępnia powiadomienia dotyczące następujących zdarzeń:

  • Transakcja
    • Zatwierdzenie
  • Menedżer stanu
    • Ponowne kompilowanie
    • Dodawanie niezawodnego stanu
    • Usuwanie niezawodnego stanu

Usługa Reliable State Manager śledzi bieżące transakcje w lotach. Jedyną zmianą stanu transakcji, która powoduje wyzwolenie powiadomienia, jest zatwierdzanie transakcji.

Usługa Reliable State Manager utrzymuje kolekcję niezawodnych stanów, takich jak Reliable Dictionary i Reliable Queue. Funkcja Reliable State Manager uruchamia powiadomienia o zmianie tej kolekcji: zostanie dodany lub usunięty stan niezawodności albo cała kolekcja zostanie ponownie skompilowana. Kolekcja Reliable State Manager została ponownie skompilowana w trzech przypadkach:

  • Odzyskiwanie: po uruchomieniu repliki odzyskuje poprzedni stan z dysku. Na końcu odzyskiwania używa funkcji NotifyStateManagerChangedEventArgs , aby uruchomić zdarzenie zawierające zestaw odzyskanych stanów niezawodnych.
  • Pełna kopia: zanim replika będzie mogła dołączyć do zestawu konfiguracji, musi zostać skompilowana. Czasami wymaga to pełnej kopii stanu programu Reliable State Manager z repliki podstawowej do zastosowania do bezczynnej repliki pomocniczej. Funkcja Reliable State Manager w replice pomocniczej używa funkcji NotifyStateManagerChangedEventArgs do wyzwalania zdarzenia zawierającego zestaw niezawodnych stanów uzyskanych z repliki podstawowej.
  • Przywracanie: w scenariuszach odzyskiwania po awarii stan repliki można przywrócić z kopii zapasowej za pośrednictwem funkcji RestoreAsync. W takich przypadkach funkcja Reliable State Manager w replice podstawowej używa funkcji NotifyStateManagerChangedEventArgs do wyzwalania zdarzenia zawierającego zestaw niezawodnych stanów przywróconych z kopii zapasowej.

Aby zarejestrować się w celu otrzymywania powiadomień dotyczących transakcji i/lub powiadomień menedżera stanu, należy zarejestrować się w zdarzeniach TransactionChanged lub StateManagerChanged w programie Reliable State Manager. Typowym miejscem do zarejestrowania się w tych programach obsługi zdarzeń jest konstruktor usługi stanowej. Po zarejestrowaniu się w konstruktorze nie zostanie pominięte żadne powiadomienie spowodowane przez zmianę w okresie istnienia klasy IReliableStateManager.

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

Procedura obsługi zdarzeń TransactionChanged używa funkcji NotifyTransactionChangedEventArgs w celu podania szczegółowych informacji o zdarzeniu. Zawiera właściwość akcji (na przykład NotifyTransactionChangedAction.Commit), która określa typ zmiany. Zawiera również właściwość transakcji, która zawiera odwołanie do zmienionej transakcji.

Uwaga

Obecnie zdarzenia TransactionChanged są zgłaszane tylko wtedy, gdy transakcja zostanie zatwierdzona. Akcja jest wtedy równa NotifyTransactionChangedAction.Commit. Jednak w przyszłości zdarzenia mogą być zgłaszane dla innych typów zmian stanu transakcji. Zalecamy sprawdzenie akcji i przetworzenie zdarzenia tylko wtedy, gdy jest to oczekiwane zdarzenie.

Poniżej przedstawiono przykładową procedurę obsługi zdarzeń TransactionChanged .

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

Procedura obsługi zdarzeń StateManagerChanged używa funkcji NotifyStateManagerChangedEventArgs , aby podać szczegółowe informacje o zdarzeniu. NotifyStateManagerChangedEventArgs ma dwie podklasy: NotifyStateManagerRebuildEventArgs i NotifyStateManagerSingleEntityChangedEventArgs. Właściwość akcji w elemencie NotifyStateManagerChangedEventArgs służy do rzutowania elementu NotifyStateManagerChangedEventArgs do poprawnej podklasy:

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

Poniżej przedstawiono przykładową procedurę obsługi powiadomień StateManagerChanged .

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

        return;
    }

    this.ProcessStateManagerSingleEntityNotification(e);
}

Powiadomienia dotyczące niezawodnego słownika

Usługa Reliable Dictionary udostępnia powiadomienia dotyczące następujących zdarzeń:

  • Ponowne kompilowanie: wywoływane, gdy element ReliableDictionary odzyskał stan z odzyskanego lub skopiowanego stanu lokalnego lub kopii zapasowej.
  • Wyczyść: wywoływane, gdy stan elementu ReliableDictionary został wyczyszczone za pomocą metody ClearAsync .
  • Dodaj: wywoływane, gdy element został dodany do elementu ReliableDictionary.
  • Aktualizacja: wywoływana, gdy element w elemencie IReliableDictionary został zaktualizowany.
  • Usuń: wywoływane, gdy element w elemencie IReliableDictionary został usunięty.

Aby uzyskać powiadomienia o niezawodnym słowniku, należy zarejestrować się w programie obsługi zdarzeń DictionaryChanged w elemencie IReliableDictionary. Typowym miejscem do zarejestrowania się w tych programach obsługi zdarzeń jest dodanie powiadomienia ReliableStateManager.StateManagerChanged . Zarejestrowanie się podczas dodawania elementu IReliableDictionary do elementu IReliableStateManager gwarantuje, że nie przegapisz żadnych powiadomień.

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

Uwaga

ProcessStateManagerSingleEntityNotification to przykładowa metoda wywołania poprzedniego przykładu OnStateManagerChangedHandler .

Powyższy kod ustawia interfejs IReliableNotificationAsyncCallback wraz ze słownikiemChanged. Ponieważ funkcja NotifyDictionaryRebuildEventArgs zawiera interfejs IAsyncEnumerable , który musi zostać wyliczony asynchronicznie- ponowne uruchomienie powiadomień jest wyzwalane za pomocą polecenia RebuildNotificationAsyncCallback zamiast 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);
    }
}

Uwaga

W poprzednim kodzie, w ramach przetwarzania powiadomienia ponownego kompilowania, najpierw zachowany stan zagregowany jest czyszczone. Ponieważ niezawodna kolekcja jest ponownie odbudowywana przy użyciu nowego stanu, wszystkie poprzednie powiadomienia są nieistotne.

Program obsługi zdarzeń DictionaryChanged używa funkcji NotifyDictionaryChangedEventArgs , aby podać szczegółowe informacje o zdarzeniu. NotifyDictionaryChangedEventArgs ma pięć podklas. Użyj właściwości akcji w elemencie NotifyDictionaryChangedEventArgs , aby rzutować właściwość NotifyDictionaryChangedEventArgs do odpowiedniej podklasy:

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

Zalecenia

  • Wykonaj jak najszybsze ukończenie zdarzeń powiadomień.
  • Nie wykonuj żadnych kosztownych operacji (na przykład operacji we/wy) w ramach zdarzeń synchronicznych.
  • Przed przetworzeniem zdarzenia sprawdź typ akcji. Nowe typy akcji mogą zostać dodane w przyszłości.

Oto kilka kwestii, o których należy pamiętać:

  • Powiadomienia są wyzwalane w ramach wykonywania operacji. Na przykład powiadomienie o przywróceniu jest wyzwalane jako ostatni krok operacji przywracania. Przywracanie nie zostanie zakończone, dopóki zdarzenie powiadomienia nie zostanie przetworzone.
  • Ponieważ powiadomienia są wyzwalane w ramach operacji stosowania, klienci widzą tylko powiadomienia dotyczące operacji zatwierdzonych lokalnie. Ponieważ operacje są gwarantowane tylko lokalnie (innymi słowy, rejestrowane), mogą one lub nie mogą być cofnięte w przyszłości.
  • Na ścieżce ponownej instalacji zostanie wyzwolone pojedyncze powiadomienie dla każdej zastosowanej operacji. Oznacza to, że jeśli transakcja T1 zawiera polecenie Create(X), Delete(X) i Create(X), otrzymasz jedno powiadomienie o utworzeniu elementu X, jeden na potrzeby usunięcia, a drugi do utworzenia ponownie w tej kolejności.
  • W przypadku transakcji zawierających wiele operacji operacje są stosowane w kolejności, w jakiej zostały odebrane na repliki podstawowej od użytkownika.
  • W ramach przetwarzania fałszywych postępów niektóre operacje mogą zostać cofnięte w replikach pomocniczych. Powiadomienia są wywoływane dla takich operacji cofania, cofanie stanu repliki z powrotem do stabilnego punktu. Jedną z ważnych różnic w powiadomieniach cofania jest to, że zdarzenia, które mają zduplikowane klucze, są agregowane. Jeśli na przykład transakcja T1 jest cofniętą, zobaczysz pojedyncze powiadomienie o metodzie Delete(X).

Następne kroki