Mencadangkan dan memulihkan Reliable Service dan Reliable Actor

Azure Service Fabric adalah platform dengan ketersediaan tinggi yang mereplikasi status di beberapa node untuk mempertahankan ketersediaan tinggi ini. Meskipun satu node dalam kluster gagal, layanan tetap tersedia. Meskipun redundansi bawaan yang disediakan oleh platform ini mungkin cukup bagi sebagian orang, dalam kasus tertentu diinginkan bagi layanan untuk mencadangkan data (ke penyimpanan eksternal).

Catatan

Sangat penting untuk mencadangkan dan memulihkan data Anda (dan menguji bahwa data berfungsi seperti yang diharapkan) sehingga Anda dapat pulih dari skenario kehilangan data.

Catatan

Microsoft merekomendasikan untuk menggunakan Cadangan dan pemulihan berkala untuk mengonfigurasi cadangan data Reliable Stateful Service dan Reliable Actor.

Contohnya, suatu layanan mungkin ingin mencadangkan datanya untuk terlindung dari skenario berikut:

  • Jika terjadi kehilangan permanen seluruh kluster Service Fabric.
  • Kehilangan sebagian besar replika partisi layanan secara permanen
  • Kesalahan administratif di mana status secara tidak sengaja dihapus atau rusak. Contohnya, administrator dengan hak istimewa yang memadai keliru menghapus layanan.
  • Bug dalam layanan yang menyebabkan kerusakan data. Contohnya, ini mungkin terjadi ketika peningkatan kode layanan mulai menulis data yang salah ke Reliable Collection. Dalam kasus seperti itu, Anda mungkin harus memulihkan kode dan data ke status sebelumnya.
  • Pemrosesan data offline. Mungkin lebih mudah untuk memiliki pemrosesan data offline untuk kecerdasan bisnis yang terjadi secara terpisah dari layanan yang menghasilkan data.

Fitur Cadangan/Pemulihan memungkinkan layanan yang dibangun di API Reliable Service untuk membuat dan memulihkan cadangan. API cadangan yang disediakan oleh platform memungkinkan cadangan status partisi layanan, tanpa memblokir operasi baca atau tulis. API pemulihan memungkinkan status partisi layanan dipulihkan dari cadangan yang dipilih.

Jenis Cadangan

Ada dua opsi cadangan: Penuh dan Inkremental. Cadangan penuh adalah cadangan yang berisi semua data yang diperlukan untuk membuat ulang status replika: titik pemeriksaan dan semua catatan log. Karena memiliki titik pemeriksaan dan log, cadangan penuh dapat dipulihkan dengan sendirinya.

Masalah dengan cadangan penuh muncul ketika titik pemeriksaan besar. Misalnya, replika yang memiliki status 16 GB akan memiliki titik pemeriksaan yang menambahkan sekitar hingga 16 GB. Jika kita memiliki Tujuan Titik Pemulihan lima menit, replika perlu dicadangkan setiap lima menit. Setiap kali mencadangkan perlu menyalin 16 GB titik pemeriksaan selain 50 MB (dapat dikonfigurasi menggunakan CheckpointThresholdInMB) senilai log.

Contoh Cadangan Penuh.

Solusi untuk masalah ini adalah cadangan inkremental, dan cadangan hanya berisi catatan log yang diubah sejak cadangan terakhir.

Contoh Cadangan Inkremental.

Karena cadangan inkremental hanya berubah sejak cadangan terakhir (tidak termasuk titik pemeriksaan), maka cenderung lebih cepat tetapi tidak dapat dipulihkan sendiri. Untuk memulihkan cadangan inkremental, diperlukan seluruh rantai cadangan. Rantai cadangan adalah rantai cadangan yang dimulai dengan cadangan penuh dan diikuti oleh sejumlah cadangan inkremental yang berseberangan.

Mengkueri Reliable Service

Penulis layanan memiliki kontrol penuh tentang kapan harus membuat cadangan dan di mana cadangan akan disimpan.

Untuk memulai cadangan, layanan perlu memanggil fungsi anggota yang diwariskan BackupAsync.
Cadangan hanya dapat dilakukan dari replika utama, dan mewajibkan pemberian status tulis.

Seperti ditunjukkan di bawah ini, BackupAsync mengambil objek BackupDescription, yang seseorang dapat menentukan cadangan penuh atau inkremental, serta fungsi callback, Func<< BackupInfo, CancellationToken, Task<bool>>> yang dipanggil ketika folder cadangan telah dibuat secara lokal dan siap untuk dipindahkan ke beberapa penyimpanan eksternal.


BackupDescription myBackupDescription = new BackupDescription(BackupOption.Incremental,this.BackupCallbackAsync);

await this.BackupAsync(myBackupDescription);

Permintaan untuk mengambil cadangan inkremental dapat gagal dengan FabricMissingFullBackupException. Pengecualian ini menunjukkan bahwa salah satu hal berikut ini terjadi:

  • replika ini tidak pernah melakukan cadangan penuh karena telah menjadi yang utama,
  • beberapa rekaman log sejak cadangan terakhir telah dipotong
  • replika melewati batas MaxAccumulatedBackupLogSizeInMB.

Pengguna dapat meningkatkan kemungkinan untuk dapat melakukan cadangan inkremental dengan mengonfigurasi MinLogSizeInMB atau TruncationThresholdFactor. Meningkatkan nilai-nilai ini akan meningkatkan penggunaan disk per replika. Untuk informasi selengkapnya, lihat Konfigurasi Reliable Services

BackupInfo menyediakan informasi mengenai cadangan, termasuk lokasi folder tempat runtime menyimpan cadangan (BackupInfo.Directory). Fungsi callback dapat memindahkan BackupInfo.Directory ke penyimpanan eksternal atau lokasi lain. Fungsi ini juga mengembalikan bool yang menunjukkan apakah berhasil memindahkan folder cadangan ke lokasi targetnya.

Kode berikut menunjukkan bagaimana metode BackupCallbackAsync dapat digunakan untuk mengunggah cadangan ke Penyimpanan Azure:

private async Task<bool> BackupCallbackAsync(BackupInfo backupInfo, CancellationToken cancellationToken)
{
    var backupId = Guid.NewGuid();

    await externalBackupStore.UploadBackupFolderAsync(backupInfo.Directory, backupId, cancellationToken);

    return true;
}

Dalam contoh sebelumnya, ExternalBackupStore adalah kelas sampel yang digunakan untuk berinteraksi dengan penyimpanan Azure Blob, dan UploadBackupFolderAsync merupakan metode yang memadatkan folder dan menempatkannya di penyimpanan Azure Blob.

Perhatikan bahwa:

  • Hanya ada satu operasi cadangan yang sedang berlangsung per replika pada waktu tertentu. Lebih dari BackupAsync satu panggilan pada satu waktu akan melempar FabricBackupInProgressException untuk membatasi cadangan dalam proses menjadi satu.
  • Jika replika gagal saat cadangan sedang berlangsung, cadangan tersebut mungkin belum selesai. Dengan demikian, setelah failover selesai, layanan bertanggung jawab untuk memulai kembali cadangan dengan memanggil BackupAsync seperlunya.

Memulihkan Reliable Services

Secara umum, kasus-kasus ketika Anda mungkin perlu melakukan operasi pemulihan, termasuk dalam salah satu kategori ini:

  • Partisi layanan kehilangan data. Misalnya, disk untuk dua dari tiga replika untuk partisi (termasuk replika utama) rusak atau dihapus. Primer baru mungkin perlu memulihkan data dari cadangan.
  • Seluruh layanan hilang. Misalnya, administrator menghapus seluruh layanan dan dengan demikian layanan dan data tersebut perlu dipulihkan.
  • Layanan mereplikasi data aplikasi yang rusak (misalnya, karena bug aplikasi). Dalam hal ini, layanan harus ditingkatkan atau dikembalikan untuk menghapus penyebab kerusakan, dan data yang tidak rusak harus dipulihkan.

Meskipun banyak pendekatan dimungkinkan, kami menawarkan beberapa contoh tentang penggunaan RestoreAsync untuk memulihkan dari skenario di atas.

Kehilangan data partisi di Reliable Services

Dalam hal ini, runtime akan secara otomatis mendeteksi kehilangan data dan memanggil OnDataLossAsync API.

Penulis layanan perlu melakukan hal berikut untuk memulihkan:

  • Mengesampingkan metode OnDataLossAsync kelas dasar virtual.
  • Menemukan cadangan terbaru di lokasi eksternal yang berisi cadangan layanan.
  • Unduh cadangan terbaru (dan dekompresi cadangan ke folder cadangan jika dikompresi).
  • Metode OnDataLossAsync ini menyediakan RestoreContext. Hubungi RestoreAsync API pada RestoreContext yang disediakan.
  • Mengembalikan true jika restorasi berhasil.

Berikut ini adalah contoh implementasi metode OnDataLossAsync:

protected override async Task<bool> OnDataLossAsync(RestoreContext restoreCtx, CancellationToken cancellationToken)
{
    var backupFolder = await this.externalBackupStore.DownloadLastBackupAsync(cancellationToken);

    var restoreDescription = new RestoreDescription(backupFolder);

    await restoreCtx.RestoreAsync(restoreDescription);

    return true;
}

RestoreDescription diteruskan ke panggilan RestoreContext.RestoreAsync berisi anggota yang disebut BackupFolderPath. Ketika memulihkan cadangan penuh tunggal, BackupFolderPath ini harus diatur ke jalur lokal folder yang berisi cadangan penuh Anda. Saat memulihkan cadangan penuh dan sejumlah cadangan inkremental, BackupFolderPath harus diatur ke jalur lokal folder yang tidak hanya berisi cadangan penuh, tetapi juga semua cadangan inkremental. Panggilan RestoreAsync dapat melempar FabricMissingFullBackupException jika BackupFolderPath yang disediakan tidak berisi cadangan penuh. Ini juga dapat melempar ArgumentException jika BackupFolderPath memiliki rantai cadangan inkremental yang rusak. Misalnya, jika berisi cadangan penuh, cadangan inkremental pertama dan cadangan inkremental ketiga tetapi tidak cadangan inkremental kedua.

Catatan

RestorePolicy diatur ke Aman secara default. Ini berarti bahwa RestoreAsync API akan gagal dengan ArgumentException jika mendeteksi bahwa folder cadangan berisi status yang lebih lama dari atau sama dengan status yang terkandung dalam replika ini. RestorePolicy.Force dapat digunakan untuk melewati pemeriksaan keamanan ini. Ini ditentukan sebagai bagian dari RestoreDescription.

Layanan yang dihapus atau hilang

Jika layanan dihapus, Anda harus terlebih dahulu membuat ulang layanan sebelum data dapat dipulihkan. Penting untuk membuat layanan dengan konfigurasi yang sama, misalnya, skema partisi, sehingga data dapat dipulihkan dengan mulus. Setelah layanan up, API untuk memulihkan data (OnDataLossAsync ke atas) harus dipanggil pada setiap partisi layanan ini. Salah satu cara mencapainya adalah dengan menggunakan FabricClient.TestManagementClient.StartPartitionDataLossAsync pada setiap partisi.

Dari titik ini, implementasinya sama dengan skenario di atas. Setiap partisi perlu memulihkan cadangan terbaru yang relevan dari penyimpanan eksternal. Satu peringatannya adalah bahwa ID partisi sekarang mungkin telah berubah, karena runtime membuat ID partisi secara dinamis. Dengan demikian, layanan perlu menyimpan informasi partisi dan nama layanan yang sesuai untuk mengidentifikasi cadangan terbaru yang benar untuk memulihkan dari untuk setiap partisi.

Catatan

Tidak disarankan untuk menggunakan FabricClient.ServiceManager.InvokeDataLossAsync pada setiap partisi untuk memulihkan seluruh layanan, karena dapat merusak status kluster Anda.

Replikasi data aplikasi yang rusak

Jika peningkatan aplikasi yang baru diterapkan memiliki bug, yang dapat menyebabkan kerusakan data. Misalnya, peningkatan aplikasi dapat mulai memperbarui setiap catatan nomor telepon dalam Reliable Dictionary dengan kode area yang tidak valid. Dalam hal ini, nomor telepon yang tidak valid akan direplikasi karena Service Fabric tidak mengetahui sifat data yang sedang disimpan.

Hal pertama yang harus dilakukan setelah Anda mendeteksi bug mengerikan yang menyebabkan kerusakan data adalah membekukan layanan di tingkat aplikasi dan, jika mungkin, tingkatkan ke versi kode aplikasi yang tidak memiliki bug. Namun, meskipun kode layanan telah diperbaiki, data mungkin masih rusak, dan dengan demikian data mungkin perlu dipulihkan. Dalam kasus seperti itu, mungkin tidak cukup untuk memulihkan cadangan terbaru, karena cadangan terbaru mungkin juga korup. Dengan demikian, Anda harus menemukan cadangan terakhir yang dibuat sebelum data rusak.

Jika Anda tidak yakin cadangan mana yang rusak, Anda dapat menyebarkan kluster Service Fabric baru dan memulihkan cadangan partisi yang terpengaruh seperti skenario "Layanan yang dihapus atau hilang" di atas. Untuk setiap partisi, mulai memulihkan cadangan dari yang terkini hingga yang terbaru. Setelah Anda menemukan cadangan yang tidak memiliki kerusakan, pindahkan/hapus semua cadangan partisi ini yang lebih baru (daripada cadangan itu). Ulangi proses ini untuk setiap partisi. Sekarang, ketika OnDataLossAsync dipanggil pada partisi di kluster produksi, cadangan terakhir yang ditemukan di penyimpanan eksternal akan menjadi yang dipilih oleh proses di atas.

Sekarang, langkah-langkah di bagian "Layanan yang dihapus atau hilang" dapat digunakan untuk memulihkan status layanan ke status sebelum kode buggy merusak status.

Perhatikan bahwa:

  • Ketika Anda memulihkan, ada kemungkinan cadangan yang dipulihkan lebih lama dari status partisi sebelum data hilang. Karena itu, Anda akan memulihkan hanya sebagai upaya terakhir untuk memulihkan data sebanyak mungkin.
  • String yang mewakili jalur folder cadangan dan jalur file di dalam folder cadangan dapat lebih besar dari 255 karakter, tergantung jalur FabricDataRoot dan panjang nama Tipe Aplikasi. Ini dapat menyebabkan beberapa metode .NET, seperti Directory.Move, untuk melemparkan pengecualian PathTooLongException. Salah satu solusinya adalah langsung memanggil API kernel32, seperti CopyFile.

Mencadangkan dan memulihkan Reliable Actor

Kerangka Kerja Reliable Actor dibangun di atas Layanan yang Dapat Diandalkan. ActorService, yang menjadi tuan rumah actor adalah layanan yang dapat diandalkan. Oleh karena itu, semua fungsi cadangan dan pemulihan yang tersedia di Reliable Service juga tersedia untuk Reliable Actor (kecuali perilaku yang spesifik dari penyedia status). Karena cadangan akan diambil berdasarkan per partisi, menyatakan untuk semua actor dalam partisi itu akan dicadangkan (dan pemulihan serupa dan akan terjadi berdasarkan per-partisi). Untuk melakukan cadangan/pemulihan, pemilik layanan harus membuat kelas layanan actor kustom yang berasal dari kelas ActorService dan kemudian melakukan backup/restore yang mirip dengan Reliable Services seperti yang dijelaskan di atas pada bagian sebelumnya.

class MyCustomActorService : ActorService
{
    public MyCustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo)
          : base(context, actorTypeInfo)
    {
    }
    
    //
    // Method overrides and other code.
    //
}

Ketika Anda membuat kelas layanan actor khusus, Anda perlu mendaftarkannya juga saat mendaftarkan actor.

ActorRuntime.RegisterActorAsync<MyActor>(
    (context, typeInfo) => new MyCustomActorService(context, typeInfo)).GetAwaiter().GetResult();

Penyedia status default untuk Reliable Actor adalah KvsActorStateProvider. Cadangan inkremental tidak diaktifkan secara default untuk KvsActorStateProvider. Anda dapat mengaktifkan cadangan inkremental dengan membuat KvsActorStateProvider menggunakan pengaturan yang sesuai di konstruktornya dan kemudian meneruskannya ke konstruktor ActorService seperti yang ditunjukkan dalam cuplikan kode berikut:

class MyCustomActorService : ActorService
{
    public MyCustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo)
          : base(context, actorTypeInfo, null, null, new KvsActorStateProvider(true)) // Enable incremental backup
    {
    }
    
    //
    // Method overrides and other code.
    //
}

Setelah cadangan inkremental diaktifkan, mengambil cadangan inkremental dapat gagal dengan FabricMissingFullBackupException karena salah satu alasan berikut dan Anda harus mengambil cadangan penuh sebelum mengambil cadangan inkremental:

  • Replika tidak pernah melakukan pencadangan penuh karena yang utama.
  • Beberapa catatan log dipotong sejak cadangan terakhir diambil.

Ketika cadangan inkremental diaktifkan, KvsActorStateProvider tidak menggunakan buffer melingkar untuk mengelola catatan lognya dan secara berkala memotongnya. Jika tidak ada cadangan yang diambil oleh pengguna selama periode 45 menit, sistem secara otomatis memangkas catatan log. Interval ini dapat dikonfigurasi dengan menentukan logTruncationIntervalInMinutes dalam konstruktor KvsActorStateProvider (mirip dengan saat mengaktifkan cadangan inkremental). Catatan log juga dapat dipotong jika replika utama perlu membangun replika lain dengan mengirimkan semua datanya.

Saat melakukan pemulihan dari rantai cadangan, mirip dengan Reliable Service, BackupFolderPath harus berisi subdirektori dengan satu subdirektori yang berisi cadangan penuh dan subdirektori lain yang berisi cadangan inkremental. API pemulihan akan melempar FabricException dengan pesan kesalahan yang sesuai jika validasi rantai cadangannya gagal.

Catatan

KvsActorStateProvider saat ini mengabaikan opsi RestorePolicy.Safe. Dukungan untuk fitur ini direncanakan dalam rilis mendatang.

Menguji Pencadangan dan Pemulihan

Penting untuk memastikan bahwa data penting sedang dicadangkan, dan dapat dipulihkan. Ini dapat dilakukan dengan memanggil cmdlet Start-ServiceFabricPartitionDataLoss di PowerShell yang dapat menginduksi kehilangan data dalam partisi tertentu untuk menguji apakah fungsi cadangan dan pemulihan data untuk layanan Anda berfungsi seperti yang diharapkan. Anda juga bisa secara terprogram memanggil kehilangan data dan memulihkan dari peristiwa itu juga.

Catatan

Anda dapat menemukan contoh implementasi fungsi cadangan dan pemulihan di Aplikasi Referensi Web di GitHub. Harap lihat layanan Inventory.Service untuk lebih jelasnya.

Pada: detail lebih lanjut tentang pencadangan dan pemulihan

Berikut ini beberapa detail selengkapnya tentang pencadangan dan pemulihan.

Cadangan

Reliable State Manager menyediakan kemampuan untuk membuat cadangan yang konsisten tanpa memblokir operasi baca atau tulis. Untuk melakukannya, ia menggunakan mekanisme titik pemeriksaan dan log persistensi. Reliable State Manager mengambil titik pemeriksaan fuzzy (ringan) pada titik-titik tertentu untuk menghilangkan tekanan dari log transaksional dan meningkatkan waktu pemulihan. Ketika BackupAsync dipanggil, Reliable State Manager menginstruksikan semua objek andal untuk menyalin file titik pemeriksaan terbaru mereka ke folder cadangan lokal. Kemudian, Reliable State Manager menyalin semua catatan log, mulai dari "penunjuk awal" hingga catatan log terbaru ke folder cadangan. Karena semua catatan log hingga catatan log terbaru disertakan dalam cadangan dan Reliable State Manager mempertahankan pencatatan penulisan di depan, Reliable State Manager menjamin bahwa semua transaksi yang dilakukan (CommitAsync berhasil dikembalikan) termasuk dalam cadangan.

Setiap transaksi yang diterapkan setelah BackupAsync dipanggil mungkin atau mungkin tidak ada dalam cadangan. Setelah folder cadangan lokal diisi oleh platform (yaitu, cadangan lokal selesai pada waktu proses), callback cadangan layanan dipanggil. Callback ini bertanggung jawab untuk memindahkan folder cadangan ke lokasi eksternal seperti Azure Storage.

Pulihkan

Reliable State Manager menyediakan kemampuan untuk memulihkan dari cadangan dengan menggunakan RestoreAsync API.
Metode RestoreAsync di RestoreContext dapat dipanggil hanya di dalam metode OnDataLossAsync. Bool yang dikembalikan oleh OnDataLossAsync menunjukkan apakah layanan memulihkan statusnya dari sumber eksternal. Jika pengembalian OnDataLossAsync true, Service Fabric akan membangun kembali semua replika lain dari primer ini. Service Fabric memastikan bahwa replika yang akan menerima panggilan OnDataLossAsync bertransisi terlebih dahulu ke peran utama tetapi tidak diberikan status baca atau status tulis. Ini menyiratkan bahwa untuk pelaksana StatefulService, RunAsync tidak akan dipanggil sampai OnDataLossAsync berhasil selesai. Kemudian, OnDataLossAsync akan dipanggil pada primer baru. Sampai layanan berhasil menyelesaikan API ini (dengan mengembalikan true atau false) dan menyelesaikan konfigurasi ulang yang relevan, API akan terus dipanggil satu per satu.

RestoreAsync pertama menghentikan semua status yang ada di replika utama yang dipanggil. Kemudian Reliable State Manager membuat semua objek Andal yang ada di folder cadangan. Selanjutnya, objek Andal diinstruksikan untuk memulihkan dari titik pemeriksaan mereka di folder cadangan. Akhirnya, Reliable State Manager memulihkan statusnya sendiri dari catatan log di folder cadangan dan melakukan pemulihan. Sebagai bagian dari proses pemulihan, operasi mulai dari "titik awal" yang telah melakukan rekaman log di folder cadangan diputar ulang ke objek Andal. Langkah ini memastikan bahwa status yang pulih konsisten.

Langkah berikutnya