Pemberitahuan Reliable Services

Notifikasi memungkinkan klien untuk melacak perubahan yang sedang dilakukan pada objek yang diminati. Dua jenis objek mendukung pemberitahuan: Reliable State Manager dan Reliable Dictionary.

Alasan umum untuk menggunakan pemberitahuan adalah:

  • Membangun tampilan terwujud, seperti indeks sekunder atau tampilan gabungan yang difilter dari status replika. Contohnya adalah indeks yang diurutkan dari semua kunci dalam Reliable Dictionary.
  • Mengirim data pemantauan, seperti jumlah pengguna yang ditambahkan dalam satu jam terakhir.

Pemberitahuan diaktifkan sebagai bagian dari penerapan operasi. Pada replika utama, operasi diterapkan setelah pengakuan kuorum sebagai bagian dari transaction.CommitAsync() atau this.StateManager.GetOrAddAsync(). Pada replika sekunder, operasi diterapkan pada pemrosesan data antrean replikasi. Karena itu, pemberitahuan harus ditangani secepat mungkin, dan peristiwa sinkron seharusnya tidak mencakup operasi yang mahal. Jika tidak, ini dapat berdampak negatif pada waktu pemrosesan transaksi serta build-up replika.

Pemberitahuan Reliable State Manager

Reliable State Manager menyediakan pemberitahuan untuk kejadian berikut:

  • Transaksi
    • Menjalankan
  • Pengelola status
    • Buat ulang
    • Penambahan reliable state
    • Penghapusan reliable state

Reliable State Manager melacak transaksi dalam penerbangan saat ini. Satu-satunya perubahan status transaksi yang menyebabkan pemberitahuan diaktifkan adalah transaksi yang dilakukan.

Reliable State Manager mengelola koleksi reliable states seperti Reliable Dictionary dan Reliable Queue. Reliable State Manager mengaktifkan pemberitahuan saat koleksi ini berubah: reliable state ditambahkan atau dihapus, atau seluruh koleksi dibuat ulang. Koleksi Reliable State Manager akan dibangun kembali dalam tiga kasus:

  • Pemulihan: Saat replika dimulai, replika akan memulihkan status sebelumnya dari disk. Pada akhir pemulihan, tindakan ini menggunakan NotifyStateManagerChangedEventArgs untuk mengaktifkan kejadian yang berisi set reliable states yang dipulihkan.
  • Salinan lengkap: Sebelum replika dapat bergabung dengan set konfigurasi, replika harus dibuat. Terkadang, hal ini memerlukan salinan lengkap status Reliable State Manager dari replika utama untuk diterapkan ke replika sekunder yang menganggur. Reliable State Manager di replika sekunder menggunakan NotifyStateManagerChangedEventArgs untuk mengaktifkan kejadian yang berisi set reliable states yang diperoleh dari replika utama.
  • Pemulihan: Dalam skenario pemulihan bencana, status replika dapat dipulihkan dari cadangan melalui RestoreAsync. Dalam kasus seperti itu, Reliable State Manager pada replika utama menggunakan NotifyStateManagerChangedEventArgs untuk mengaktifkan kejadian yang berisi set reliable states yang dipulihkan dari cadangan.

Untuk mendaftar pemberitahuan transaksi dan/atau pemberitahuan state manager, Anda perlu mendaftar dengan kejadian TransactionChanged atau StateManagerChanged di Reliable State Manager. Tempat umum untuk mendaftar dengan penanganan aktivitas ini adalah konstruktor layanan stateful Anda. Saat Anda mendaftar pada konstruktor, Anda tidak akan melewatkan pemberitahuan apa pun yang disebabkan oleh perubahan selama masa pakai IReliableStateManager.

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

Penangan aktivitas TransactionChanged menggunakan NotifyTransactionChangedEventArgs untuk memberikan detail tentang kejadian tersebut. Ini berisikan properti tindakan (misalnya, NotifyTransactionChangedAction.Commit) yang menentukan jenis perubahan. Ini juga berisi properti transaksi yang memberikan referensi ke transaksi yang berubah.

Catatan

Hari ini, kejadian TransactionChanged dimunculkan hanya jika transaksi dilakukan. Tindakan tersebut kemudian sama dengan NotifyTransactionChangedAction.Commit. Namun di masa mendatang, kejadian mungkin dimunculkan untuk jenis perubahan status transaksi lainnya. Sebaiknya periksa tindakan dan pemrosesan tindakan hanya jika tindakan tersebut salah satu yang Anda harapkan.

Berikut adalah contoh penanganan aktivitas 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);
    }
}

Penangan aktivitas StateManagerChanged menggunakan NotifyStateManagerChangedEventArgs untuk memberikan detail tentang kejadian tersebut. NotifyStateManagerChangedEventArgs memiliki dua subkelas: NotifyStateManagerRebuildEventArgs dan NotifyStateManagerSingleEntityChangedEventArgs. Anda menggunakan properti tindakan di NotifyStateManagerChangedEventArgs untuk mentransmisikan NotifyStateManagerChangedEventArgs ke subkelas yang benar:

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

Berikut adalah contoh penangan pemberitahuan StateManagerChanged.

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

        return;
    }

    this.ProcessStateManagerSingleEntityNotification(e);
}

Pemberitahuan Reliable Dictionary

Reliable Dictionary memberikan pemberitahuan untuk kejadian-kejadian berikut:

  • Bangun ulang: Dipanggil ketika ReliableDictionary telah memulihkan statusnya dari status atau cadangan lokal yang dipulihkan atau disalin.
  • Bersihkan: Dipanggil ketika status ReliableDictionary telah dihapus melalui metode ClearAsync.
  • Tambahkan: Dipanggil ketika item telah ditambahkan ke ReliableDictionary.
  • Perbarui: Dipanggil ketika item di IReliableDictionary telah diperbarui.
  • Hapus: Dipanggil ketika item di IReliableDictionary telah dihapus.

Untuk mendapatkan pemberitahuan Reliable Dictionary, Anda harus mendaftar dengan penanganan aktivitas DictionaryChanged di IReliableDictionary. Tempat umum untuk mendaftar dengan penanganan aktivitas ini adalah di tambahkan pemberitahuan ReliableStateManager.StateManagerChanged. Mendaftar ketika IReliableDictionary ditambahkan ke IReliableStateManager memastikan bahwa Anda tidak akan melewatkan pemberitahuan apa pun.

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

Catatan

ProcessStateManagerSingleEntityNotification adalah metode sampel yang dipanggil oleh contoh OnStateManagerChangedHandler sebelumnya.

Kode sebelumnya mengatur antarmuka IReliableNotificationAsyncCallback, bersama dengan DictionaryChanged. Karena NotifyDictionaryRebuildEventArgs berisi antarmuka IAsyncEnumerable - yang perlu dihitung secara asinkron - notifikasi pembangunan kembali dijalankan melalui RebuildNotificationAsyncCallback alih-alih 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);
    }
}

Catatan

Dalam kode sebelumnya, sebagai bagian dari pemrosesan notifikasi pembangunan kembali, pertama-tama, status agregat yang dipertahankan akan dibersihkan. Karena reliable collection sedang dibangun kembali dengan keadaan baru, semua pemberitahuan sebelumnya menjadi tidak relevan.

Penangan aktivitas DictionaryChanged menggunakan NotifyDictionaryChangedEventArgs untuk memberikan detail tentang kejadian tersebut. NotifyDictionaryChangedEventArgs memiliki lima subkelas. Gunakan properti tindakan di NotifyDictionaryChangedEventArgs untuk mentransmisikan NotifyDictionaryChangedEventArgs ke subkelas yang benar:

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

Rekomendasi

  • Selesaikan kejadian pemberitahuan secepat mungkin.
  • Janganjalankan operasi yang mahal (misalnya, operasi I/O) sebagai bagian dari kejadian sinkron.
  • Periksa jenis tindakan sebelum Anda memproses kejadian. Jenis tindakan baru mungkin ditambahkan di masa mendatang.

Berikut beberapa hal yang perlu diperhatikan:

  • Pemberitahuan diaktifkan sebagai bagian dari pelaksanaan operasi. Misalnya, pemberitahuan pemulihan diaktifkan sebagai langkah akhir dari operasi pemulihan. Pemulihan tidak akan selesai sampai tindakan pemberitahuan diproses.
  • Karena pemberitahuan diaktifkan sebagai bagian dari operasi penerapan, klien hanya melihat pemberitahuan untuk operasi yang dilakukan secara lokal. Dan karena operasi dijamin hanya untuk dilakukan secara lokal (dengan kata lain, dicatat), operasi tersebut mungkin atau mungkin tidak dibatalkan di masa mendatang.
  • Di jalur pengulangan, satu notifikasi diaktifkan untuk setiap operasi yang diterapkan. Ini berarti jika transaksi T1 menyertakan Create(X), Delete(X), dan Create(X), Anda akan mendapatkan satu notifikasi untuk pembuatan X, satu untuk penghapusan, dan satu untuk pembuatan lagi, dalam urutan tersebut.
  • Untuk transaksi yang berisi beberapa operasi, operasi diterapkan dalam urutan yang diterima pada replika utama dari pengguna.
  • Sebagai bagian dari pemrosesan kemajuan palsu, beberapa operasi mungkin dibatalkan pada replika sekunder. Pemberitahuan dimunculkan untuk operasi pengurungan tersebut, mengembalikan status replika ke titik stabil. Satu perbedaan penting dari pemberitahuan pengurungan adalah bahwa peristiwa yang memiliki kunci duplikat akan digabungkan. Misalnya, jika transaksi T1 dibatalkan, Anda akan melihat satu pemberitahuan ke Delete(X).

Langkah berikutnya