Bagikan melalui


Praktik terbaik dalam Orleans

Orleans dibangun untuk sangat menyederhanakan pembangunan aplikasi terdistribusi yang dapat diskalakan, terutama untuk cloud. Orleans menemukan Model Aktor Virtual sebagai sebuah evolusi dari Model Aktor yang dioptimalkan untuk skenario komputasi awan.

Biji-bijian (aktor virtual) adalah blok penyusun dasar aplikasi yang berbasis pada Orleans. Mereka merangkum status dan perilaku entitas aplikasi dan mempertahankan siklus hidup mereka. Model pemrograman Orleans dan karakteristik runtime-nya cocok dengan beberapa jenis aplikasi yang lebih baik daripada yang lain. Dokumen ini dimaksudkan untuk menangkap beberapa pola aplikasi yang teruji dan terbukti berfungsi dengan baik di Orleans.

Aplikasi yang sesuai

Pertimbangkan Orleans kapan:

  • Jumlah signifikan (ratusan, jutaan, miliaran, dan bahkan triliunan) entitas yang digabungkan secara longgar. Untuk memberikan konteks pada angka ini, Orleans dapat dengan mudah menciptakan sesuatu bagi setiap orang di Bumi dalam suatu kelompok kecil, selama suatu subset dari jumlah total tersebut aktif setiap saat.
    • Contoh: profil pengguna, pesanan pembelian, sesi aplikasi/game, saham.
  • Entitas cukup kecil agar dapat dijalankan dalam satu utas.
    • Contoh: Tentukan apakah saham harus dibeli berdasarkan harga saat ini.
  • Beban kerja bersifat interaktif.
    • Contoh: permintaan-tanggapan (request-response), mulai/pantau/selesaikan (start/monitor/complete).
  • Lebih dari satu server diharapkan atau mungkin diperlukan.
    • Orleans berjalan pada kluster yang diperluas dengan menambahkan server untuk memperluas kluster.
  • Koordinasi global tidak diperlukan atau dalam skala yang lebih kecil antara beberapa entitas pada satu waktu.
    • Skalabilitas dan performa eksekusi dicapai dengan paralelisasi dan mendistribusikan sejumlah besar tugas yang sebagian besar independen tanpa titik sinkronisasi tunggal.

Aplikasi yang tidak cocok

Orleans kurang cocok ketika:

  • Memori harus dibagikan antar entitas.
    • Setiap biji-bijian mempertahankan statusnya dan tidak boleh dibagikan.
  • Sejumlah kecil entitas besar mungkin multithreaded.
    • Layanan mikro mungkin menjadi pilihan yang lebih baik saat mendukung logika kompleks dalam satu layanan.
  • Koordinasi global dan/atau konsistensi diperlukan.
    • Koordinasi global semacam itu akan sangat membatasi performa aplikasi yang berbasis Orleans. Orleans dibangun untuk dengan mudah menskalakan ke skala global tanpa perlu koordinasi manual mendalam.
  • Operasi yang berjalan untuk waktu yang lama.
    • Pekerjaan batch, tugas Single Instruction Multiple Data (SIMD).
    • Ini tergantung pada kebutuhan aplikasi dan mungkin cocok untuk Orleans.

Gambaran umum Biji-Bijian

  • Butir menyerupai objek. Namun, mereka didistribusikan, virtual, dan asinkron.
  • Mereka digabungkan secara longgar, terisolasi, dan terutama independen.
    • Setiap biji-bijian dienkapsulasi yang juga mempertahankan keadaannya secara independen dari biji-bijian lainnya.
    • Biji-bijian gagal sendiri-sendiri.
  • Hindari komunikasi cerewet antara biji-bijian.
    • Penggunaan memori langsung secara signifikan lebih murah daripada lewat pesan.
    • Biji-bijian yang sangat cerewet mungkin lebih baik dikombinasikan sebagai satu biji-bijian.
    • Kompleksitas/Ukuran argumen dan serialisasi perlu dipertimbangkan.
    • Deserialisasi dua kali mungkin lebih mahal daripada mengirim ulang pesan biner.
  • Hindari hambatan.
    • Koordinator tunggal/Registri/Monitor.
    • Lakukan agregasi bertahap jika diperlukan.

Asinkronisitas

  • Tidak ada pemblokiran thread: Semua item harus Asinkron (Task Asynchronous Programming (TAP)).
  • menunggu adalah sintaks terbaik untuk digunakan saat menyusun operasi asinkron.
  • Skenario Umum:
    • Mengembalikan nilai konkret:

    • return Task.FromResult(value);

    • Kembalikan Task dengan jenis yang sama:

    • return foo.Bar();

    • await dan Task lanjutkan eksekusi:

      var x = await bar.Foo();
      
      var y = DoSomething(x);
      
      return y;
      
    • Penyebaran

      var tasks = new List<Task>();
      
      foreach (var grain in grains)
      {
          tasks.Add(grain.Foo());
      }
      await Task.WhenAll(tasks);
      
      DoMoreWork();
      

Implementasi biji-bijian

  • Jangan pernah melakukan operasi penguncian utas dalam grain. Semua operasi selain komputasi lokal harus secara eksplisit asinkron.
    • Contoh: Secara sinkron menunggu operasi IO atau panggilan layanan web, mengunci, menjalankan perulangan berlebihan yang menunggu kondisi, dan sebagainya.
  • Kapan menggunakan StatelessWorkerAttribute:
    • Operasi fungsional seperti dekripsi, dekompresi, dan persiapan sebelum diteruskan untuk diproses.
    • Ketika hanya biji-bijian lokal yang diperlukan dalam beberapa aktivasi.
    • Contoh: Berkinerja baik dengan agregasi bertahap dalam silo lokal terlebih dahulu.
  • Biji-bijian secara bawaan tidak dapat dimasuki ulang.
    • Kebuntuan (deadlock) dapat terjadi karena siklus panggilan.
    • Contoh:
    • Biji-bijian memanggil dirinya sendiri.
    • Grain A memanggil B yang memanggil C yang pada gilirannya memanggil A (A -> B -> C -> A).
    • Grain A memanggil Grain B sebagai Grain B memanggil Grain A (A -> B -> A).
    • Batas waktu digunakan untuk memecah kebuntuan secara otomatis.
    • ReentrantAttribute dapat digunakan untuk mengizinkan masuknya kembali kelas biji-bijian.
    • Reentrant tetap berulir tunggal; namun, dapat menginterkalasi (membagi pemrosesan/memori antar tugas).
    • Menangani interleaving meningkatkan risiko dengan menjadi rawan kesalahan.
  • Warisan:
    • Kelas biji-bijian mewarisi dari kelas dasar Biji-bijian. Antarmuka biji-bijian (satu atau beberapa) dapat ditambahkan ke setiap butir.
    • Disambiguasi mungkin diperlukan untuk mengimplementasikan antarmuka yang sama di beberapa kelas biji-bijian.
  • Penggunaan generik didukung.

Persistensi keadaan biji-bijian

OrleansAPI persistensi status grain dirancang agar mudah digunakan dan menyediakan fungsionalitas penyimpanan yang dapat diperluas.

  • Orleans.IGrainState diperluas oleh antarmuka .NET yang berisi bidang yang harus disertakan dalam status biji-bijian yang bertahan.
  • Grain dipertahankan dengan menggunakan IPersistentState TState<> yang diperluas oleh kelas grain yang menambahkan properti yang sangat diketuk kuat State ke dalam kelas dasar grain.
  • Grain<TGrainState>.ReadStateAsync() Awal secara otomatis terjadi sebelumnya ActiveAsync() telah dipanggil untuk biji-bijian.
  • Ketika data dari objek status grain diubah, maka grain harus memanggil Grain<TGrainState>.WriteStateAsync().
    • Biasanya, grain memanggil State.WriteStateAsync() di akhir metode grain untuk mengembalikan janji Write.
    • Penyedia Penyimpanan dapat mencoba mengelompokkan operasi penulisan yang dapat meningkatkan efisiensi, tetapi kontrak dan konfigurasi perilaku ortogonal (independen) dari API penyimpanan yang digunakan oleh grain.
    • Timer adalah metode alternatif untuk menulis pembaruan secara berkala.
    • Timer memungkinkan aplikasi untuk menentukan jumlah "konsistensi akhir"/keadaan tanpa status yang diizinkan.
    • Waktu (langsung/tidak ada/menit) juga dapat dikontrol kapan harus diperbarui.
    • PersistentStateAttribute kelas yang didekorasi, seperti kelas biji-bijian lainnya, hanya dapat dikaitkan dengan satu penyedia penyimpanan.
    • Atribut StorageProvider(ProviderName = "name") mengaitkan kelas grain dengan penyedia tertentu.
    • <StorageProvider> perlu ditambahkan ke dalam file konfigurasi silo yang juga harus mencantumkan "nama" yang sesuai dari [StorageProvider(ProviderName="name")].

Penyedia penyimpanan

Penyedia penyimpanan bawaan:

  • Orleans. Penyimpanan menampung semua penyedia penyimpanan bawaan.

  • MemoryStorage (Data yang disimpan dalam memori tanpa persistensi tahan lama) hanya digunakan untuk penelusuran kesalahan dan pengujian unit.

  • AzureTableStorage:

    • Konfigurasikan informasi akun penyimpanan Azure dengan opsional AzureTableStorageOptions.DeleteStateOnClear (penghapusan keras atau lunak).
    • Orleans serializer menyimpan data JSON secara efisien dalam satu sel tabel Azure.
    • Batas ukuran data == ukuran maksimum kolom Azure yang merupakan 64kb data biner.
    • Kode yang dikontribusikan komunitas yang memperluas penggunaan beberapa kolom tabel yang meningkatkan ukuran maksimum keseluruhan menjadi 1MB.

Tips pemecahan masalah penyedia penyimpanan

  • TraceOverride Verbose3 akan mencatat lebih banyak informasi lebih lanjut tentang operasi penyimpanan.
    • Perbarui file konfigurasi silo.
    • LogPrefix="Storage" untuk semua penyedia, atau jenis tertentu menggunakan "Storage.Memory" / "Storage.Azure" / "Storage.Shard".

Cara menangani kegagalan operasi penyimpanan:

  • Biji-bijian dan penyedia penyimpanan dapat menunggu proses penyimpanan dan mengulangi kegagalan sesuai kebutuhan.
  • Kegagalan yang tidak tertangani akan menyebar kembali ke pemanggil dan akan dilihat oleh klien sebagai janji yang rusak.
  • Selain bacaan awal, tidak ada konsep yang secara otomatis menghancurkan aktivasi jika operasi penyimpanan gagal.
  • Mencoba kembali penyimpanan yang gagal bukanlah fitur default untuk penyedia penyimpanan bawaan.

Tips ketahanan biji-bijian

Ukuran biji-bijian:

  • Throughput optimal dicapai dengan menggunakan banyak butir-butir yang lebih kecil daripada sedikit butir yang lebih besar. Namun, praktik terbaik memilih ukuran dan jenis biji-bijian didasarkan pada model domain aplikasi.
    • Contoh: Pengguna, Pesanan, dll.

Data perubahan eksternal:

  • Biji-bijian dapat membaca ulang data status saat ini dari penyimpanan dengan menggunakan State.ReadStateAsync().

  • Timer juga dapat digunakan untuk membaca ulang data dari penyimpanan secara berkala.

    • Persyaratan fungsional dapat didasarkan pada "keusangan" informasi yang sesuai.
    • Contoh: Tingkat kehalusan cache konten.
  • Menambahkan dan menghapus bidang.

    • Penyedia penyimpanan akan menentukan efek menambahkan dan menghapus bidang tambahan dari statusnya yang bertahan.
    • Tabel Azure tidak mendukung skema dan harus secara otomatis menyesuaikan dengan bidang tambahan.

Menulis penyedia kustom:

  • Penyedia penyimpanan mudah ditulis yang juga merupakan elemen ekstensi yang signifikan untuk Orleans.
  • Kontrak API API GrainState mendorong kontrak API penyimpanan (Write, Clear, ReadStateAsync).
  • Perilaku penyimpanan biasanya dapat dikonfigurasi (Penulisan batch, Penghapusan Keras atau Lunak, dan sebagainya) dan didefinisikan oleh penyedia penyimpanan.

Manajemen kluster

  • Orleans secara otomatis mengelola kluster.
    • Node yang gagal --yaitu dapat gagal dan bergabung kapan saja-- secara otomatis ditangani oleh Orleans.
    • Tabel instans silo yang sama yang dibuat untuk protokol pengklusteran juga dapat digunakan untuk diagnostik. Tabel menyimpan riwayat semua silo dalam kluster.
    • Ada juga opsi konfigurasi deteksi kegagalan yang agresif atau lebih lenient.
  • Kegagalan dapat terjadi kapan saja dan merupakan kejadian normal.
    • Jika silo gagal, biji-bijian yang diaktifkan pada silo yang gagal akan secara otomatis diaktifkan kembali nanti pada silo lain dalam kluster.
    • Biji-bijian bisa habis. Solusi coba lagi seperti Polly dapat membantu percobaan ulang.
    • Orleans memberikan jaminan pengiriman pesan di mana setiap pesan dikirimkan sekali saja.
    • Pemanggil bertanggung jawab untuk mencoba kembali panggilan yang gagal jika diperlukan.
    • Praktik umumnya adalah mengulangi kembali dari ujung ke ujung pada pihak klien/antarmuka depan.

Manajemen penyebaran dan produksi

Menskalakan keluar dan masuk:

  • Memantau Perjanjian Service-Level (SLA)
  • Menambahkan atau Menghapus instans
  • Orleans secara otomatis menyeimbangkan kembali dan memanfaatkan perangkat keras baru. Namun, biji-bijian yang diaktifkan tidak diseimbangkan kembali ketika silo baru ditambahkan ke kluster.

Pengelogan dan pengujian

  • Pengelogan, Pelacakan, dan Pemantauan:
    • Masukkan pengelogan menggunakan injeksi dependensi:

      public HelloGrain(ILogger<HelloGrain> logger)
      {
          _logger = logger;
      }
      
    • Microsoft.Extensions.Logging digunakan untuk pengelogan fungsional dan fleksibel.

Pengujian:

  • Microsoft.Orleans.TestingHost Paket NuGet berisi TestCluster yang dapat digunakan untuk membuat kluster dalam memori, terdiri dari dua silo secara default, yang dapat digunakan untuk menguji butir.
  • Untuk informasi selengkapnya, lihat Pengujian unit dengan Orleans.

Pemecahan Masalah:

  • Gunakan keanggotaan berbasis tabel Azure untuk pengembangan dan pengujian.
    • Bekerja dengan Emulator Azure Storage untuk pemecahan masalah lokal.
    • Tabel OrleansSiloInstances menampilkan status kluster.
    • Gunakan ID penyebaran unik (kunci partisi) untuk membuatnya sederhana.
  • Silo tidak dapat mulai.
    • Periksa OrleansSiloInstances untuk menentukan apakah silo terdaftar di sana.
    • Pastikan firewall terbuka untuk port TCP: 11111 dan 30000.
    • Periksa log, termasuk log tambahan yang berisi kesalahan startup.
  • Frontend (Klien) tidak dapat tersambung ke kluster silo.
    • Klien harus dihosting dalam layanan yang sama dengan silo.
    • Periksa OrleansSiloInstances untuk memastikan silo (gateway) terdaftar.
    • Periksa log klien untuk memastikan bahwa gateway cocok dengan yang tercantum dalam tabel OrleansSiloInstances.
    • Periksa log klien untuk memvalidasi bahwa klien dapat tersambung ke satu atau beberapa gateway.