Manajemen kluster di Orleans

Orleans menyediakan manajemen kluster melalui protokol keanggotaan bawaan, terkadang disebut sebagai keanggotaan Kluster. Tujuan dari protokol ini adalah agar semua silo (Orleans server) menyetujui kumpulan silo yang sedang aktif, mendeteksi silo yang bermasalah, dan memungkinkan silo baru untuk bergabung dengan kluster.

Konfigurasi protokol keanggotaan

Protokol keanggotaan menggunakan konfigurasi default berikut:

  • Setiap silo dipantau oleh 10 silo lainnya
  • 2 kecurigaan diperlukan untuk menyatakan silo mati
  • Kecurigaan berlaku selama 3 menit
  • Sinyal dikirim setiap 10 detik
  • 3 pemeriksaan terlewat memicu kecurigaan

Dengan default ini, waktu deteksi kegagalan umum adalah sekitar 15 detik. Dalam skenario pemulihan bencana di mana silo gagal tanpa pembersihan yang tepat, kluster menggunakan tanda waktu IAmAlive (diperbarui setiap 30 detik secara default) untuk memulihkan; silo yang belum memperbarui tanda waktunya selama beberapa periode akan diabaikan selama pemeriksaan konektivitas pada tahap pemulaan. Dengan melewatkan silo yang tidak responsif ini, silo baru dapat dimulai dan dengan cepat membersihkan kluster silo yang tidak berfungsi dengan menyatakan mereka mati.

Konfigurasi

Anda dapat mengonfigurasi pengaturan protokol keanggotaan menggunakan ClusterMembershipOptions:

siloBuilder.Configure<ClusterMembershipOptions>(options =>
{
    // Number of silos each silo monitors (default: 10)
    options.NumProbedSilos = 10;

    // Number of suspicions required to declare a silo dead (default: 2)
    options.NumVotesForDeathDeclaration = 2;

    // Time window for suspicions to be valid (default: 180 seconds)
    options.DeathVoteExpirationTimeout = TimeSpan.FromSeconds(180);

    // Interval between probes (default: 10 seconds)
    options.ProbeTimeout = TimeSpan.FromSeconds(10);

    // Number of missed probes before suspecting a silo (default: 3)
    options.NumMissedProbesLimit = 3;
});

Kapan harus menyesuaikan pengaturan

Dalam kebanyakan kasus, pengaturan default sesuai. Namun, Anda mungkin mempertimbangkan penyesuaian dalam skenario ini:

  • Jaringan latensi tinggi: Tingkatkan ProbeTimeout jika silo Anda didistribusikan di seluruh wilayah dengan latensi jaringan tinggi.
  • Persyaratan ketersediaan kritis: Kurangi DeathVoteExpirationTimeout untuk deteksi kegagalan yang lebih cepat, tetapi berhati-hatilah terhadap positif palsu.

Konfigurasi protokol keanggotaan

Protokol keanggotaan menggunakan konfigurasi default berikut:

  • Setiap silo dipantau oleh 3 silo lainnya
  • 2 kecurigaan diperlukan untuk menyatakan silo mati
  • Kecurigaan berlaku selama 3 menit
  • Sinyal dikirim setiap 10 detik
  • 3 pemeriksaan terlewat memicu kecurigaan

Konfigurasi protokol keanggotaan

Protokol keanggotaan menggunakan konfigurasi default berikut:

  • Setiap silo dipantau oleh 3 silo lainnya
  • 2 kecurigaan diperlukan untuk menyatakan silo mati
  • Kecurigaan berlaku selama 3 menit

Protokol bergantung pada layanan eksternal untuk memberikan abstraksi IMembershipTable. IMembershipTable adalah tabel datar dan tahan lama yang digunakan untuk dua tujuan. Pertama, ini berfungsi sebagai titik pertemuan bagi silo untuk menemukan satu sama lain dan bagi Orleans klien untuk menemukan silo. Kedua, ia menyimpan pandangan keanggotaan saat ini (daftar silo yang aktif) dan membantu mengoordinasikan kesepakatan tentang pandangan ini.

Implementasi IMembershipTable resmi berikut saat ini tersedia:

Konfigurasi Klasterisasi Redis

Konfigurasikan Redis sebagai penyedia pengklusteran menggunakan UseRedisClustering metode ekstensi:

using StackExchange.Redis;

var builder = Host.CreateApplicationBuilder(args);

builder.UseOrleans(siloBuilder =>
{
    siloBuilder.UseRedisClustering(options =>
    {
        options.ConfigurationOptions = new ConfigurationOptions
        {
            EndPoints = { "localhost:6379" },
            AbortOnConnectFail = false
        };
    });
});

Atau, Anda dapat menggunakan string koneksi:

siloBuilder.UseRedisClustering("localhost:6379");

Kelas ini RedisClusteringOptions menyediakan opsi konfigurasi berikut:

Harta benda Tipe Description
ConfigurationOptions ConfigurationOptions Konfigurasi klien StackExchange.Redis. Dibutuhkan.
EntryExpiry TimeSpan? Waktu kedaluwarsa opsional untuk entri. Hanya atur ini untuk lingkungan ephemeral seperti pengujian. Defaultnya adalah null.
CreateMultiplexer Func<RedisClusteringOptions, Task<IConnectionMultiplexer>> Pabrik kustom untuk membuat multiplexer koneksi Redis.
CreateRedisKey Func<ClusterOptions, RedisKey> Fungsi kustom untuk menghasilkan kunci Redis untuk tabel keanggotaan. Format defaultnya adalah {ServiceId}/members/{ClusterId}.

Penting

IMembershipTable Implementasi antarmuka harus menggunakan penyimpanan data yang tahan lama. Misalnya, jika Anda menggunakan Redis, pastikan persistensi diaktifkan secara eksplisit. Konfigurasi volatil dapat mengakibatkan tidak tersedianya kluster.

Aspire integrasi untuk pengklusteran

Saat menggunakan Aspire, Anda dapat mengonfigurasi Orleans pengklusteran secara deklaratif di proyek AppHost Anda. Aspire secara otomatis menyuntikkan konfigurasi yang diperlukan ke dalam proyek silo Anda melalui variabel lingkungan.

Klasterisasi Redis dengan Aspire

Proyek AppHost (Program.cs):

var builder = DistributedApplication.CreateBuilder(args);

var redis = builder.AddRedis("redis");

var orleans = builder.AddOrleans("cluster")
    .WithClustering(redis);

builder.AddProject<Projects.MySilo>("silo")
    .WithReference(orleans)
    .WithReference(redis);

builder.Build().Run();

Proyek Silo (Program.cs):

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedRedisClient("redis");
builder.UseOrleans();

builder.Build().Run();

Pengklusteran Penyimpanan Tabel Azure dengan Aspire

Proyek AppHost (Program.cs):

var builder = DistributedApplication.CreateBuilder(args);

var storage = builder.AddAzureStorage("storage")
    .RunAsEmulator();  // Use Azurite for local development
var tables = storage.AddTables("clustering");

var orleans = builder.AddOrleans("cluster")
    .WithClustering(tables);

builder.AddProject<Projects.MySilo>("silo")
    .WithReference(orleans)
    .WaitFor(storage);

builder.Build().Run();

Proyek Silo (Program.cs):

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedAzureTableServiceClient("clustering");
builder.UseOrleans();

builder.Build().Run();

Petunjuk / Saran

Untuk menggunakan emulator Azurite untuk pengembangan lokal, panggil .RunAsEmulator() sumber daya Azure Storage. Tanpa panggilan ini, Aspire mengharapkan koneksi Azure Storage yang sebenarnya.

Azure Cosmos DB klasterisasi dengan Aspire

Proyek AppHost (Program.cs):

var builder = DistributedApplication.CreateBuilder(args);

var cosmos = builder.AddAzureCosmosDB("cosmos")
    .RunAsEmulator();  // Use emulator for local development
var database = cosmos.AddCosmosDatabase("orleans");

var orleans = builder.AddOrleans("cluster")
    .WithClustering(database);

builder.AddProject<Projects.MySilo>("silo")
    .WithReference(orleans)
    .WaitFor(cosmos);

builder.Build().Run();

Proyek Silo (Program.cs):

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddKeyedAzureCosmosClient("cosmos");
builder.UseOrleans();

builder.Build().Run();

Nota

AspireIntegrasi Cosmos DB untuk Orleans saat ini hanya mendukung pengklusteran. Untuk penyimpanan dan pengingat biji-bijian dengan Cosmos DB, Anda harus mengonfigurasi penyedia tersebut secara manual dalam proyek silo.

Penting

Anda harus memanggil metode yang sesuai AddKeyed* (seperti AddKeyedRedisClient, , AddKeyedAzureTableServiceClientatau AddKeyedAzureCosmosClient) untuk mendaftarkan sumber daya cadangan dalam kontainer injeksi dependensi. Orleans provider mencari resource berdasarkan nama layanan yang diberi kunci—jika Anda melewati langkah ini, Orleans tidak akan dapat menyelesaikan resource dan akan memunculkan kesalahan penyelesaian dependensi saat runtime.

Untuk informasi selengkapnya tentang Orleans dan Aspire integrasi, lihat Orleans dan Aspire integrasi.

Mengonfigurasi pengklusteran Cassandra

Konfigurasikan Apache Cassandra sebagai penyedia pengklusteran menggunakan UseCassandraClustering metode ekstensi. Install Microsoft.Orleans.Clustering.Cassandra NuGet Package:

dotnet add package Microsoft.Orleans.Clustering.Cassandra

Konfigurasikan pengklusteran Cassandra dengan string koneksi:

using Orleans.Clustering.Cassandra.Hosting;

var builder = Host.CreateApplicationBuilder(args);

builder.UseOrleans(siloBuilder =>
{
    siloBuilder.UseCassandraClustering(
        connectionString: "Contact Points=localhost;Port=9042",
        keyspace: "orleans");
});

Atau, gunakan konfigurasi berbasis opsi untuk kontrol lebih lanjut:

siloBuilder.UseCassandraClustering(options =>
{
    options.ConfigureClient("Contact Points=cassandra-node1,cassandra-node2;Port=9042", "orleans");
    options.UseCassandraTtl = true;
    options.InitializeRetryMaxDelay = TimeSpan.FromSeconds(30);
});

Atau sediakan pabrik sesi kustom untuk skenario tingkat lanjut:

using Cassandra;

siloBuilder.UseCassandraClustering(async serviceProvider =>
{
    var cluster = Cluster.Builder()
        .AddContactPoints("cassandra-node1", "cassandra-node2")
        .WithPort(9042)
        .WithCredentials("username", "password")
        .WithQueryOptions(new QueryOptions().SetConsistencyLevel(ConsistencyLevel.Quorum))
        .Build();

    return await cluster.ConnectAsync("orleans");
});

Kelas ini CassandraClusteringOptions menyediakan opsi konfigurasi berikut:

Harta benda Tipe Bawaan Description
UseCassandraTtl bool false Ketika true, mengonfigurasi time-to-live untuk baris tabel keanggotaan di Cassandra, memungkinkan pembersihan silo yang tidak berfungsi bahkan jika kluster tidak lagi berjalan. DefunctSiloExpiration digunakan dari ClusterMembershipOptions.
InitializeRetryMaxDelay TimeSpan 20 detik Penundaan maksimum antara percobaan ulang saat mengalami konflik selama inisialisasi. Ini biasanya diperlukan dengan sejumlah besar silo yang terhubung secara bersamaan ke kluster Cassandra multi-data center.

Kapan menggunakan pengklusteran Cassandra

Pertimbangkan Cassandra untuk pengklusteran saat:

  • Anda sudah memiliki infrastruktur Cassandra di organisasi Anda
  • Anda memerlukan penyedia pengklusteran yang berfungsi di beberapa pusat data dengan konsistensi yang dapat disetel
  • Anda memerlukan pembersihan silo yang tidak berfungsi secara otomatis melalui Cassandra TTL bahkan ketika kelompok Orleans tidak berjalan
  • Anda memerlukan kecepatan throughput penulisan yang tinggi untuk kluster besar

Konfigurasikan kluster Azure Cosmos DB

Konfigurasikan Azure Cosmos DB sebagai penyedia pengklusteran menggunakan UseCosmosClustering metode ekstensi. Instal paket Microsoft.Orleans.Clustering.Cosmos NuGet:

dotnet add package Microsoft.Orleans.Clustering.Cosmos

Konfigurasikan pengklusteran Cosmos DB dengan string koneksi:

using Azure.Identity;

var builder = Host.CreateApplicationBuilder(args);

builder.UseOrleans(siloBuilder =>
{
    siloBuilder.UseCosmosClustering(options =>
    {
        options.ConfigureCosmosClient(
            "https://myaccount.documents.azure.com:443/",
            new DefaultAzureCredential());
        options.DatabaseName = "Orleans";
        options.ContainerName = "OrleansCluster";
        options.IsResourceCreationEnabled = true;
    });
});

Atau, Anda dapat menggunakan string koneksi:

siloBuilder.UseCosmosClustering(options =>
{
    options.ConfigureCosmosClient("AccountEndpoint=https://myaccount.documents.azure.com:443/;AccountKey=...");
});

Kelas CosmosClusteringOptions mewarisi dari CosmosOptions dan menyediakan opsi konfigurasi berikut:

Harta benda Tipe Bawaan Description
DatabaseName string "Orleans" Nama dari database Cosmos DB.
ContainerName string "OrleansCluster" Nama kontainer untuk data keanggotaan kluster.
IsResourceCreationEnabled bool false Ketika true, secara otomatis membuat database dan kontainer jika tidak ada.
DatabaseThroughput int? null Tingkat pemrosesan yang disediakan untuk database. Jika null, menggunakan mode tanpa server.
ContainerThroughputProperties ThroughputProperties? null Properti throughput (penyampaian) untuk kontainer.
ClientOptions CosmosClientOptions new() Opsi diteruskan ke klien Cosmos DB.
CleanResourcesOnInitialization bool false Menghapus database pada inisialisasi. Hanya untuk pengujian.

Kapan menggunakan pengklusteran Cosmos DB

Pertimbangkan Azure Cosmos DB untuk pengklusteran saat:

  • Anda sudah menggunakan Azure Cosmos DB di aplikasi Anda
  • Anda memerlukan database terdistribusi secara global dengan kemampuan penulisan multi-wilayah
  • Anda menginginkan opsi tanpa server yang dikelola sepenuhnya dengan penskalakan otomatis
  • Anda memerlukan pembacaan dan penulisan berlatensi rendah dengan jaminan SLA

Untuk klien Orleans, gunakan UseCosmosGatewayListProvider untuk mengonfigurasi penemuan gateway.

builder.UseOrleansClient(clientBuilder =>
{
    clientBuilder.UseCosmosGatewayListProvider(options =>
    {
        options.ConfigureCosmosClient(
            "https://myaccount.documents.azure.com:443/",
            new DefaultAzureCredential());
    });
});

Selain IMembershipTable, setiap silo berpartisipasi dalam protokol keanggotaan antar-rekan yang sepenuhnya terdistribusi, yang mendeteksi silo yang gagal dan mencapai kesepakatan tentang set silo yang aktif. Implementasi internal Orleans dari protokol keanggotaan dijelaskan di bawah ini.

Protokol keanggotaan

  1. Saat memulai, setiap silo menambahkan entri untuk dirinya sendiri ke dalam tabel yang sudah diketahui bersama menggunakan implementasi IMembershipTable. Orleans menggunakan kombinasi identitas silo (ip:port:epoch) dan ID penyebaran layanan (ID kluster) sebagai kunci unik dalam tabel. Epoch hanyalah waktu dalam satuan waktu ketika silo ini dimulai, memastikan bahwa ip:port:epoch adalah unik dalam penyebaran tertentu Orleans.

  2. Silos memantau satu sama lain secara langsung melalui pemeriksaan aplikasi ("apakah Anda hidup" heartbeats). Sonda dikirim sebagai pesan langsung dari silo ke silo melalui soket TCP yang sama yang digunakan untuk komunikasi reguler. Dengan cara ini, pengujian sepenuhnya berkorelasi dengan masalah jaringan aktual dan kesehatan server. Setiap silo memeriksa sekumpulan silo lain yang dapat dikonfigurasi. Silo memilih siapa yang akan diselidiki dengan menghitung hash yang konsisten pada identitas silo lain, membentuk cincin virtual dari semua identitas, dan memilih X silo penerus dalam cincin tersebut. (Ini adalah teknik terdistribusi terkenal yang disebut hashing yang konsisten dan banyak digunakan dalam banyak tabel hash terdistribusi, seperti Chord DHT).

  3. Jika silo S tidak menerima balasan pemeriksaan Y dari server P yang diawasi, silo tersebut mencurigai P dengan mencatat kecurigaannya beserta cap waktu ke dalam baris P di IMembershipTable.

  4. Jika P memiliki lebih dari kecurigaan Z dalam waktu K detik, S menulis bahwa P mati ke dalam baris P dan menyiarkan rekam jepret tabel keanggotaan saat ini ke semua silo lainnya. Silo memperbarui tabel secara berkala, sehingga rekaman gambaran adalah sebuah langkah pengoptimalan untuk mengurangi waktu yang diperlukan oleh semua silo guna memahami tampilan keanggotaan baru.

  5. Secara lebih rinci:

    1. Kecurigaan ditulis pada IMembershipTable, dalam kolom khusus dalam baris yang sesuai dengan P. Ketika S mencurigai P, ia menulis: "pada ketika TTT S mencurigai P".

    2. Satu kecurigaan tidak cukup untuk menyatakan P mati. Anda memerlukan kecurigaan Z dari silo yang berbeda dalam jendela waktu yang dapat dikonfigurasi T (biasanya 3 menit) untuk menyatakan P mati. Asumsi ditulis menggunakan kontrol konkurensi optimis yang disediakan oleh IMembershipTable.

    3. Silo S yang curiga membaca baris P.

    4. Jika S adalah tersangka terakhir (sudah ada tersangka Z-1 dalam periode T, seperti yang dicatat di kolom kecurigaan), S memutuskan untuk menyatakan P mati. Dalam hal ini, S menambahkan dirinya ke daftar tersangka dan juga menulis di kolom Status P bahwa P adalah Mati.

    5. Jika tidak, jika S bukan tersangka terakhir, S hanya menambahkan dirinya ke kolom tersangka.

    6. Dalam kedua kasus, write-back menggunakan nomor versi atau ETag yang dibaca sebelumnya, menserialisasikan pembaruan ke baris ini. Jika penulisan gagal karena ketidakcocokan versi/ETag, S mencoba kembali (membaca lagi dan mencoba menulis, kecuali P sudah ditandai mati).

    7. Pada tingkat tinggi, urutan "baca, modifikasi lokal, tulis balik" ini adalah transaksi. Namun demikian, transaksi penyimpanan tidak selalu digunakan. Kode "transaksi" dijalankan secara lokal di server, dan konkurensi optimis yang disediakan oleh IMembershipTable memastikan isolasi dan atomisitas.

  6. Setiap silo secara berkala membaca seluruh tabel keanggotaan untuk penyebarannya. Dengan cara ini, silo mengetahui tentang silo baru yang bergabung dan tentang silo lain yang dianggap mati.

  7. Siaran rekam jepret: Untuk mengurangi frekuensi pembacaan tabel berkala, setiap kali silo menulis ke tabel (kecurigaan, gabungan baru, dll.), ia mengirim rekam jepret status tabel saat ini ke semua silo lainnya. Karena tabel keanggotaan konsisten dan diberi versi monoton, setiap pembaruan menghasilkan rekam jepret versi unik yang dapat dibagikan dengan aman. Ini memungkinkan penyebaran segera perubahan keanggotaan tanpa menunggu siklus baca berkala. Pembacaan berkala masih dipertahankan sebagai mekanisme cadangan jika distribusi cuplikan gagal.

  8. Tampilan keanggotaan yang diurutkan: Protokol keanggotaan memastikan semua konfigurasi keanggotaan diurutkan secara global dengan urutan yang sepenuhnya total. Pemesanan ini memberikan dua manfaat utama:

    1. Konektivitas terjamin: Ketika silo baru bergabung dengan kluster, konektivitas dua arah harus divalidasi ke setiap silo aktif lainnya. Jika ada silo yang ada tidak merespons (berpotensi menunjukkan masalah konektivitas jaringan), silo baru tidak diizinkan untuk bergabung. Ini memastikan konektivitas penuh antara semua silo dalam kluster pada waktu mulai. Lihat catatan tentang IAmAlive di bawah ini untuk pengecualian dalam skenario pemulihan bencana.

    2. Pembaruan direktori yang konsisten: Protokol tingkat yang lebih tinggi, seperti direktori biji-bijian terdistribusi, mengandalkan semua silo yang memiliki tampilan keanggotaan monotonik yang konsisten. Ini memungkinkan resolusi aktivasi biji-bijian duplikat yang lebih cerdas. Untuk detail lebih lanjut, lihat dokumentasi direktori Grain.

    Rincian implementasi:

    1. IMembershipTable memerlukan pembaruan atom untuk menjamin urutan keseluruhan perubahan secara global.

      • Implementasi harus memperbarui entri tabel (daftar silo) dan nomor versi secara atomik.
      • Mencapai ini menggunakan transaksi database (seperti di SQL Server) atau operasi perbandingan dan pertukaran atomik menggunakan ETags (seperti dalam Penyimpanan Tabel Azure).
      • Mekanisme khusus tergantung pada kemampuan sistem penyimpanan yang mendasar.
    2. Baris versi keanggotaan khusus dalam tabel melacak perubahan:

      • Setiap penulisan ke tabel (kecurigaan, deklarasi kematian, penggabungan) menaikkan nomor versi ini.
      • Semua penulisan diproses secara berurutan melalui baris ini menggunakan pembaruan atomik.
      • Versi yang meningkat secara monotonis memastikan urutan total dari semua perubahan keanggotaan.
    3. Ketika silo S memperbarui status silo P:

      • S pertama-tama membaca status tabel terbaru.
      • Dalam satu operasi atomik, ini memperbarui baris P dan menaikkan nomor versi.
      • Jika pembaruan atom gagal (misalnya, karena modifikasi bersamaan), operasi akan mencoba lagi dengan mundur bertahap secara eksponensial.

    pertimbangan skalabilitas :

    Mengatur urutan semua penulisan data melalui baris versi dapat memengaruhi skalabilitas karena peningkatan persaingan. Protokol ini telah terbukti efektif dalam produksi dengan hingga 200 silo tetapi mungkin menghadapi tantangan di luar seribu silo. Untuk penyebaran yang sangat besar, bagian lain dari Orleans (pesan, direktori grain, hosting) tetap dapat diskalakan bahkan jika pembaruan keanggotaan menjadi faktor penghambat.

  9. Konfigurasi default: Konfigurasi default telah disetel dengan tangan selama penggunaan produksi di Azure. Secara default: setiap silo dipantau oleh tiga silo lainnya, dua kecurigaan sudah cukup untuk menyatakan silo mati, dan kecurigaan hanya dipertimbangkan dari tiga menit terakhir (jika tidak, mereka sudah kedaluarsa). Sinyal dikirim setiap sepuluh detik, dan Anda baru akan mencurigai silo setelah melewatkan tiga sinyal.

  10. Pemantauan mandiri : Detektor kesalahan menggabungkan ide-ide dari riset Hashicorp Lifeguard (makalah, presentasi, blog) untuk meningkatkan stabilitas kluster selama peristiwa bencana di mana sebagian besar kluster mengalami kegagalan parsial. Komponen LocalSiloHealthMonitor menilai kesehatan setiap silo menggunakan beberapa heuristik:

    • Status aktif dalam tabel keanggotaan
    • Tidak ada kecurigaan dari silo lain
    • Respons pemeriksaan terbaru yang berhasil
    • Permintaan pemeriksaan terbaru diterima
    • Responsivitas kumpulan utas (item kerja yang dijalankan dalam waktu 1 detik)
    • Akurasi timer (berfungsi dalam 3 detik dari jadwal)

    Skor kesehatan silo mempengaruhi batas waktu pemeriksaannya: silo yang tidak sehat (skor 1-8) memiliki batas waktu yang lebih lama dibandingkan dengan silo sehat (skor 0). Ini memberikan dua manfaat:

    • Memberikan lebih banyak waktu agar pemeriksaan berhasil ketika jaringan atau sistem mengalami stres.
    • Membuatnya lebih mungkin bahwa silo yang tidak sehat dipilih mati sebelum mereka salah dapat memilih silo yang sehat.

    Ini sangat berharga selama skenario seperti kelaparan kumpulan utas, di mana simpul lambat mungkin salah mencurigai simpul sehat hanya karena mereka tidak dapat memproses respons dengan cukup cepat.

  11. Pemeriksaan tidak langsung: Fitur lain yang terinspirasi oleh Lifeguard meningkatkan akurasi pendeteksian kegagalan dengan mengurangi kemungkinan silo yang tidak sehat atau terisolasi secara keliru menyatakan silo yang sehat sebagai mati. Ketika silo pemantauan memiliki dua upaya pemeriksaan yang tersisa untuk silo target sebelum memberikan suara untuk menyatakannya mati, ia menggunakan pemeriksaan tidak langsung:

    • Silo pemantauan secara acak memilih silo lain sebagai perantara dan memintanya untuk memeriksa target.
    • Perantara mencoba menghubungi silo yang dituju.
    • Jika target gagal merespons dalam periode waktu habis, perantara mengirimkan pengakuan negatif.
    • Jika silo pemantauan menerima pengakuan negatif dari perantara, dan perantara menyatakan dirinya sehat (melalui pemantauan mandiri, dijelaskan di atas), silo pemantauan memberikan suara untuk menyatakan target mati.
    • Dengan konfigurasi default yang membutuhkan dua suara, pengakuan negatif dari pemeriksaan tidak langsung dihitung sebagai kedua suara, memungkinkan deklarasi cepat terhadap silo yang mati ketika beberapa perspektif mengonfirmasi kegagalan.
  12. Menegakkan deteksi kegagalan yang sempurna: Setelah sebuah silo dinyatakan mati dalam tabel, semua orang menganggapnya mati, bahkan jika sebenarnya belum benar-benar mati (misalnya, hanya terpartisi sementara atau pesan heartbeat hilang). Semua orang berhenti berkomunikasi dengannya. Setelah silo mengetahui bahwa ia sudah mati (dengan membaca status barunya dari tabel), ia akan mengakhiri prosesnya. Akibatnya, infrastruktur harus ada untuk memulai ulang silo sebagai sebuah proses baru (nomor epoch baru dihasilkan setelah mulai). Saat dihosting di Azure, ini terjadi secara otomatis. Jika tidak, infrastruktur lain diperlukan, seperti Layanan Windows yang dikonfigurasi untuk secara otomatis memulai ulang jika terjadi kegagalan atau penempatan Kubernetes.

  13. Apa yang terjadi jika tabel tidak dapat diakses selama beberapa waktu:

    Ketika layanan penyimpanan tidak berfungsi, tidak tersedia, atau mengalami masalah komunikasi, Orleans protokol tidak salah menyatakan silo mati. Silo operasional terus bekerja tanpa masalah. Namun, Orleans tidak akan dapat menyatakan silo mati (jika mendeteksi silo mati melalui pemeriksaan yang terlewat, itu tidak dapat mencatatnya di dalam tabel) dan tidak akan dapat mengizinkan silo baru bergabung. Jadi, kelengkapan menderita, tetapi akurasi tidak—pemartisian dari tabel tidak pernah menyebabkan Orleans keliru menyatakan silo mati. Juga, dalam partisi jaringan parsial (di mana beberapa silo dapat mengakses tabel dan yang lain tidak dapat), Orleans mungkin menyatakan silo mati, tetapi perlu waktu bagi semua silo lain untuk mempelajarinya. Deteksi mungkin tertunda, tetapi Orleans tidak pernah salah membunuh silo karena tabel tidak tersedia.

  14. IAmAlive menulis tentang diagnostik dan pemulihan bencana:

    Selain heartbeat yang dikirim antar silo, setiap silo secara berkala memperbarui tanda waktu "I Am Alive" di baris tabelnya. Ini melayani dua tujuan:

    1. Diagnostik: Menyediakan cara sederhana kepada administrator sistem untuk memeriksa keaktifan kluster dan menentukan kapan silo terakhir aktif. Tanda waktu secara default diperbarui setiap 30 detik.

    2. Pemulihan bencana: Jika silo belum memperbarui tanda waktunya selama beberapa periode (dikonfigurasi melalui NumMissedTableIAmAliveLimit, default: 3), silo baru mengabaikannya selama pemeriksaan konektivitas startup. Ini memungkinkan kluster untuk pulih dari skenario di mana silo mengalami kerusakan tanpa pembersihan yang tepat.

Tabel keanggotaan

Seperti disebutkan, IMembershipTable berfungsi sebagai titik pertemuan bagi silo untuk menemukan satu sama lain dan bagi Orleans klien untuk menemukan silo. Ini juga membantu mengoordinasikan perjanjian tentang pandangan keanggotaan.

Daftar berikut berisi catatan implementasi untuk beberapa implementasi resmi dari IMembershipTable:

  1. Penyimpanan Tabel Azure: Dalam implementasi ini, ID penyebaran Azure berfungsi sebagai kunci partisi, dan identitas silo (ip:port:epoch) bertindak sebagai kunci baris. Bersama-sama, mereka menjamin kunci unik per silo. Untuk kontrol konkurensi, kontrol konkurensi optimis berdasarkan Azure Table ETags digunakan. Setiap kali data dibaca dari tabel, ETag untuk setiap baris baca disimpan dan digunakan saat mencoba menulis ulang. Layanan Azure Table secara otomatis menetapkan dan memeriksa ETag pada setiap tulisan. Untuk transaksi multi-baris, dukungan untuk transaksi batch yang disediakan oleh Azure Table digunakan, menjamin transaksi yang dapat diserialisasikan melalui baris dengan kunci partisi yang sama.

  2. SQL Server: Dalam implementasi ini, ID penyebaran yang dikonfigurasi membedakan antara penyebaran dan silo mana yang termasuk dalam penyebaran mana. Identitas silo didefinisikan sebagai kombinasi deploymentID, ip, port, epoch dalam tabel dan kolom yang sesuai. Backend relasional menggunakan kontrol dan transaksi konkurensi optimis, mirip dengan menggunakan ETags dalam implementasi Azure Table. Implementasi relasional mengharapkan mesin database menghasilkan ETag. Untuk SQL Server 2000, ETag yang dihasilkan diperoleh dari panggilan ke NEWID(). Pada SQL Server 2005 dan yang lebih baru, ROWVERSION digunakan. Orleans membaca dan menulis ETag relasional sebagai tag buram VARBINARY(16) dan menyimpannya dalam memori sebagai string yang dikodekan base64 . Orleans mendukung penyisipan multi-baris menggunakan UNION ALL (untuk Oracle, termasuk DUAL), yang saat ini digunakan untuk menyisipkan data statistik. Implementasi dan alasan yang tepat untuk SQL Server tersedia di CreateOrleansTables_SqlServer.sql.

  3. Apache ZooKeeper: Dalam implementasi ini, ID penyebaran yang dikonfigurasi digunakan sebagai simpul akar, dan identitas silo (ip:port@epoch) sebagai simpul anaknya. Mereka menjamin setiap silo memiliki jalur unik. Untuk kontrol konkurensi, kontrol konkurensi optimis berdasarkan versi node digunakan. Setiap kali data dibaca dari simpul akar penyebaran, versi untuk setiap simpul silo anak yang dibaca disimpan dan digunakan saat mencoba mengembalikan penulisan. Setiap kali data node berubah, layanan ZooKeeper secara atom meningkatkan nomor versi. Untuk transaksi multibaris, metode multi digunakan, menjamin transaksi yang dapat diserialisasikan melalui simpul silo dengan node ID penyebaran induk yang sama.

  4. HashiCorp Consul: Penyimpanan Kunci/Nilai Konsul digunakan untuk mengimplementasikan tabel keanggotaan. Lihat Penyebaran Consul untuk detail selengkapnya.

  5. AWS DynamoDB: Dalam implementasi ini, ID Penyebaran kluster digunakan sebagai Kunci Partisi dan Identitas Silo (ip-port-generation) sebagai RangeKey, membuat rekaman unik. Konkurensi optimis dicapai dengan menggunakan atribut ETag melalui penulisan bersyarat di DynamoDB. Logika implementasinya cukup mirip dengan Penyimpanan Tabel Azure.

  6. Apache Cassandra: Dalam implementasi ini, komposit ID Layanan dan ID Kluster berfungsi sebagai kunci partisi, dan identitas silo (ip:port:epoch) sebagai kunci baris. Bersama-sama, mereka menjamin baris yang unik untuk setiap silo. Untuk kontrol konkurensi, digunakan kontrol konkurensi optimis berdasarkan versi kolom statis dengan menggunakan Transaksi Ringan. Kolom versi ini dibagikan untuk semua baris dalam partisi/kluster, menyediakan nomor versi bertahap yang konsisten untuk setiap tabel keanggotaan kluster. Tidak ada transaksi multi-baris dalam implementasi ini.

  7. Emulasi dalam memori untuk penyiapan pengembangan: Butir sistem khusus digunakan untuk implementasi ini. Biji-bijian ini hidup pada silo utama yang ditunjuk, yang hanya digunakan untuk penyiapan pengembangan. Dalam penggunaan produksi nyata apa pun, silo utama tidak diperlukan.

Alasan desain

Pertanyaan yang wajar mungkin adalah mengapa tidak sepenuhnya mengandalkan Apache ZooKeeper atau etcd untuk implementasi keanggotaan kluster, dengan potensi menggunakan dukungan bawaan dari ZooKeeper untuk keanggotaan grup dengan node sementara? Mengapa menerapkan protokol keanggotaan kami? Terutama ada tiga alasan:

  1. Penyebaran/Hosting di awan:

    Zookeeper bukan layanan yang dihosting. Ini berarti di lingkungan Cloud, Orleans pelanggan harus menyebarkan, menjalankan, dan mengelola instans kluster ZK mereka. Ini adalah beban yang tidak perlu yang tidak dipaksakan pada pelanggan. Dengan menggunakan Azure Table, Orleans bergantung pada layanan terkelola yang dihosting, membuat kehidupan pelanggan jauh lebih sederhana. Pada dasarnya, di Cloud, gunakan Cloud sebagai Platform, bukan Infrastruktur. Di sisi lain, saat menjalankan sistem di lokasi dan mengelola server Anda, mengandalkan ZK sebagai implementasi dari IMembershipTable adalah opsi yang layak.

  2. Deteksi Langsung Kegagalan:

    Saat menggunakan keanggotaan grup ZK dengan simpul ephemeral, deteksi kegagalan terjadi antara Orleans server (klien ZK) dan server ZK. Ini mungkin belum tentu berkorelasi dengan masalah jaringan aktual antar Orleans server. Keinginannya adalah bahwa deteksi kegagalan secara akurat mencerminkan status komunikasi intra-kluster. Secara khusus, dalam desain ini, jika Orleans silo tidak dapat berkomunikasi dengan IMembershipTable, itu tidak dianggap mati dan dapat terus bekerja. Sebaliknya, jika keanggotaan grup ZK menggunakan simpul yang bersifat sementara, pemutusan sambungan dari server ZK dapat menyebabkan Orleans silo (klien ZK) dinyatakan mati, padahal mungkin sebenarnya masih hidup dan berfungsi secara penuh.

  3. Portabilitas dan fleksibilitas:

    Sebagai bagian Orleansdari filosofi, Orleans tidak memaksa ketergantungan yang kuat pada teknologi tertentu melainkan memberikan desain yang fleksibel di mana komponen yang berbeda dapat dengan mudah dialihkan dengan implementasi yang berbeda. Ini persis tujuan abstraksi IMembershipTable diperuntukkan.

Properti protokol keanggotaan

  1. Dapat menangani sejumlah kegagalan:

    Algoritma ini dapat menangani sejumlah kegagalan (f<=n), termasuk mulai ulang kluster penuh. Ini kontras dengan solusi berbasis Paxos "tradisional", yang membutuhkan kuorum (biasanya mayoritas). Situasi produksi telah menunjukkan skenario di mana lebih dari setengah silo tidak berfungsi. Sistem ini tetap berfungsi, sementara keanggotaan berbasis Paxos tidak akan dapat membuat kemajuan.

  2. Lalu lintas ke meja sangat ringan:

    Pemeriksaan aktual langsung di antara server, bukan ke tabel. Pengujian perutean melalui tabel akan meningkatkan lalu lintas jaringan yang signifikan dan kurang akurat dari sisi deteksi kegagalan - jika silo tidak dapat mencapai tabel, maka akan melewatkan mencatat detak jantung "Saya hidup", dan sistem lain akan menganggapnya mati.

  3. Akurasi yang dapat diatur versus kelengkapan:

    Meskipun Anda tidak dapat mencapai deteksi kegagalan yang sempurna dan akurat, biasanya Anda menginginkan kemampuan untuk menukar akurasi (tidak ingin menyatakan silo yang masih hidup sebagai mati) dengan kelengkapan (ingin menyatakan silo yang sudah mati sebagai mati sesegera mungkin). Konfigurasi suara untuk mendeklarasikan pemeriksaan yang gagal dan terlewat memungkinkan penyeimbangan kedua aspek ini. Untuk informasi selengkapnya, lihat Yale University: Detektor Kegagalan Ilmu Komputer.

  4. Skala:

    Protokol dapat menangani ribuan, bahkan mungkin puluhan ribu, server. Ini kontras dengan solusi tradisional berbasis Paxos, seperti protokol komunikasi grup, yang diketahui tidak dapat skalanya lebih dari beberapa puluh simpul.

  5. Diagnostik:

    Tabel ini juga sangat nyaman untuk diagnostik dan pemecahan masalah. Administrator sistem dapat secara instan menemukan daftar silo aktif saat ini dalam tabel, serta melihat sejarah semua silo yang dinonaktifkan dan kecurigaan. Ini sangat berguna saat mendiagnosis masalah.

  6. Mengapa penyimpanan persisten yang andal diperlukan untuk implementasi IMembershipTable:

    Penyimpanan persisten digunakan untuk IMembershipTable dalam dua tujuan. Pertama, ini berfungsi sebagai titik pertemuan bagi silo untuk menemukan satu sama lain dan bagi Orleans klien untuk menemukan silo. Kedua, penyimpanan yang andal membantu mengoordinasikan perjanjian pada tampilan keanggotaan. Sementara deteksi kegagalan terjadi secara langsung peer-to-peer antara silo, tampilan keanggotaan disimpan dalam penyimpanan yang andal, dan mekanisme kontrol konkurensi yang disediakan oleh penyimpanan ini digunakan untuk mencapai perjanjian tentang siapa yang hidup dan siapa yang mati. Dalam arti tertentu, protokol ini mengalihdayakan tantangan berat konsensus terdistribusi ke cloud. Dengan demikian, kekuatan penuh platform cloud yang mendasari digunakan, menggunakannya secara nyata sebagai Platform as a Service (PaaS).

  7. Penulisan langsung IAmAlive ke dalam tabel hanya digunakan untuk tujuan diagnostik:

    Selain heartbeat yang dikirim antar silo-silo, setiap silo juga secara berkala memperbarui kolom "I Am Alive" pada baris tabelnya. Kolom "I Am Alive" ini hanya digunakan untuk pemecahan masalah dan diagnostik manual dan tidak digunakan oleh protokol keanggotaan itu sendiri. Biasanya ditulis pada frekuensi yang jauh lebih rendah (sekali setiap 5 menit) dan berfungsi sebagai alat yang sangat berguna bagi administrator sistem untuk memeriksa keakuratan kluster atau dengan mudah mengetahui kapan silo terakhir hidup.

Pengakuan

Pengakuan atas kontribusi Alex Kogan terhadap desain dan implementasi versi pertama protokol ini. Pekerjaan ini dilakukan sebagai bagian dari magang musim panas di Microsoft Research pada musim panas 2011. Penerapan berbasis IMembershipTable ZooKeeper dilakukan oleh Shay Hazor, implementasi SQL IMembershipTable dilakukan oleh Veikko Eeva, implementasi AWS DynamoDB IMembershipTable dilakukan oleh Gutemberg Ribeiro, implementasi berbasis IMembershipTable Consul dilakukan oleh Paul North, dan akhirnya implementasi Apache Cassandra IMembershipTable diadaptasi dari OrleansCassandraUtilsArshia001.