Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Biji-bijian dapat memiliki beberapa objek data persisten bernama yang terkait dengannya. Objek status ini dimuat dari penyimpanan selama aktivasi biji-bijian sehingga tersedia selama permintaan. Persistensi butir menggunakan model plugin yang dapat diperluas, memungkinkan Anda menggunakan penyedia penyimpanan untuk database apa pun. Model persistensi ini dirancang untuk kesederhanaan dan tidak dimaksudkan untuk mencakup semua pola akses data. Biji-bijian juga dapat mengakses database secara langsung tanpa menggunakan model persistensi biji-bijian.
Dalam diagram sebelumnya, UserGrain memiliki status Profil dan status Keranjang, masing-masing disimpan dalam sistem penyimpanan terpisah.
Tujuan
- Mendukung beberapa objek data persisten bernama per butir.
- Izinkan beberapa penyedia penyimpanan yang dikonfigurasi, masing-masing berpotensi memiliki konfigurasi yang berbeda dan didukung oleh sistem penyimpanan yang berbeda.
- Memungkinkan komunitas mengembangkan dan menerbitkan penyedia penyimpanan.
- Berikan penyedia penyimpanan kontrol penuh atas cara mereka menyimpan data status grain di penyimpanan backing persisten. Corollary: Orleans tidak menyediakan solusi penyimpanan ORM yang komprehensif tetapi memungkinkan penyedia penyimpanan kustom untuk mendukung persyaratan ORM tertentu sesuai kebutuhan.
Paket
Anda dapat menemukan Orleans penyedia penyimpanan biji-bijian di NuGet. Paket yang dikelola secara resmi meliputi:
- Microsoft.Orleans. Persistence.AdoNet: Untuk database SQL dan sistem penyimpanan lainnya yang didukung oleh ADO.NET. Untuk informasi selengkapnya, lihat persistensi grain ADO.NET.
- Microsoft.Orleans. Persistence.AzureStorage: Untuk Azure Storage, termasuk Azure Blob Storage dan Azure Table Storage (melalui Azure Table Storage API). Untuk informasi selengkapnya, lihat Persistensi butir Azure Storage.
- Microsoft.Orleans. Persistence.Cosmos: Penyedia Azure Cosmos DB. Untuk informasi selengkapnya, lihat Persistensi butir Azure Cosmos DB.
- Microsoft.Orleans. Persistence.DynamoDB: Untuk Amazon DynamoDB. Untuk informasi selengkapnya, lihat Persistensi butir Amazon DynamoDB.
Antarmuka Pemrograman Aplikasi (API)
Biji-bijian berinteraksi dengan status persisten mereka menggunakan IPersistentState<TState>, di mana TState
adalah jenis status yang dapat diserialisasikan:
public interface IPersistentState<TState> : IStorage<TState>
{
}
public interface IStorage<TState> : IStorage
{
TState State { get; set; }
}
public interface IStorage
{
string Etag { get; }
bool RecordExists { get; }
Task ClearStateAsync();
Task WriteStateAsync();
Task ReadStateAsync();
}
public interface IPersistentState<TState> where TState : new()
{
TState State { get; set; }
string Etag { get; }
Task ClearStateAsync();
Task WriteStateAsync();
Task ReadStateAsync();
}
Orleans menyuntikkan instans dari IPersistentState<TState>
ke dalam grain sebagai parameter konstruktor. Anda dapat membuat anotasi parameter ini dengan PersistentStateAttribute atribut untuk mengidentifikasi nama status yang disuntikkan dan nama penyedia penyimpanan yang menyediakannya. Contoh berikut menunjukkan ini dengan menyuntikkan dua state bernama ke dalam konstruktor UserGrain
.
public class UserGrain : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
private readonly IPersistentState<CartState> _cart;
public UserGrain(
[PersistentState("profile", "profileStore")] IPersistentState<ProfileState> profile,
[PersistentState("cart", "cartStore")] IPersistentState<CartState> cart)
{
_profile = profile;
_cart = cart;
}
}
Jenis butir yang berbeda dapat menggunakan penyedia penyimpanan yang dikonfigurasi yang berbeda, bahkan jika keduanya adalah jenis yang sama (misalnya, dua instans penyedia Azure Table Storage yang berbeda yang terhubung ke akun Azure Storage yang berbeda).
Status Baca
Keadaan biji-bijian secara otomatis dibaca ketika biji-bijian diaktifkan, tetapi biji-bijian bertanggung jawab untuk secara eksplisit memicu pembaruan untuk perubahan keadaan biji-bijian jika diperlukan.
Jika objek ingin secara eksplisit membaca ulang status terbarunya dari penyimpanan cadangan, ia harus memanggil metode ReadStateAsync. Ini memuat ulang status biji-bijian dari penyimpanan persisten melalui penyedia penyimpanan. Salinan dalam memori sebelumnya dari status grain ditimpa dan diganti ketika Task
dari ReadStateAsync()
selesai.
Akses nilai status menggunakan State
properti . Misalnya, metode berikut mengakses status profil yang dinyatakan dalam kode di atas:
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
Tidak perlu memanggil ReadStateAsync()
selama operasi normal; Orleans memuat status secara otomatis selama aktivasi. Namun, Anda dapat menggunakan ReadStateAsync()
untuk menyegarkan status yang dimodifikasi secara eksternal.
Lihat bagian Mode kegagalan di bawah ini untuk detail tentang mekanisme penanganan kesalahan.
Menulis status
Anda dapat mengubah status melalui State
properti . Status yang dimodifikasi tidak secara otomatis bertahan. Sebagai gantinya, Anda memutuskan kapan harus mempertahankan status dengan memanggil WriteStateAsync metode . Misalnya, metode berikut memperbarui properti pada State
dan menyimpan status yang diperbarui:
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
Secara konseptual, Orleans Runtime membuat duplikat penuh dari objek data status grain untuk digunakan dalam setiap operasi penulisan. Di balik layar, runtime mungkin menggunakan aturan pengoptimalan dan heuristik untuk menghindari melakukan sebagian atau seluruh salinan mendalam dalam keadaan tertentu, asalkan semantik isolasi logis yang diharapkan dipertahankan.
Lihat bagian Mode kegagalan di bawah ini untuk detail tentang mekanisme penanganan kesalahan.
Bersihkan status
Metode ClearStateAsync ini menghapus status biji-bijian dalam penyimpanan. Bergantung pada penyedia, operasi ini mungkin secara opsional menghapus status grain sepenuhnya.
Mulai sekarang!
Sebelum biji-bijian dapat menggunakan persistensi, Anda harus mengonfigurasi penyedia penyimpanan pada silo.
Pertama, konfigurasikan penyedia penyimpanan, satu untuk status profil dan satu untuk status keranjang.
using IHost host = new HostBuilder()
.UseOrleans(siloBuilder =>
{
siloBuilder.AddAzureTableGrainStorage(
name: "profileStore",
configureOptions: options =>
{
// Configure the storage connection key
options.ConfigureTableServiceClient(
"DefaultEndpointsProtocol=https;AccountName=data1;AccountKey=SOMETHING1");
})
.AddAzureBlobGrainStorage(
name: "cartStore",
configureOptions: options =>
{
// Configure the storage connection key
options.ConfigureTableServiceClient(
"DefaultEndpointsProtocol=https;AccountName=data2;AccountKey=SOMETHING2");
});
})
.Build();
var host = new HostBuilder()
.UseOrleans(siloBuilder =>
{
siloBuilder.AddAzureTableGrainStorage(
name: "profileStore",
configureOptions: options =>
{
// Use JSON for serializing the state in storage
options.UseJson = true;
// Configure the storage connection key
options.ConnectionString =
"DefaultEndpointsProtocol=https;AccountName=data1;AccountKey=SOMETHING1";
})
.AddAzureBlobGrainStorage(
name: "cartStore",
configureOptions: options =>
{
// Use JSON for serializing the state in storage
options.UseJson = true;
// Configure the storage connection key
options.ConnectionString =
"DefaultEndpointsProtocol=https;AccountName=data2;AccountKey=SOMETHING2";
});
})
.Build();
Penting
Microsoft menyarankan agar Anda menggunakan alur autentikasi paling aman yang tersedia. Jika Anda menyambungkan ke Azure SQL, Identitas Terkelola untuk sumber daya Azure adalah metode autentikasi yang direkomendasikan.
Setelah mengonfigurasi penyedia penyimpanan bernama "profileStore"
, Anda dapat mengakses penyedia ini dari butiran.
Anda dapat menambahkan status persisten ke biji-bijian dengan dua cara utama:
- Dengan menyuntikkan
IPersistentState<TState>
ke dalam konstruktor objek. - Dengan mewarisi dari Grain<TGrainState>.
Cara yang disarankan untuk menambahkan penyimpanan ke biji-bijian adalah dengan menyuntikkan IPersistentState<TState>
ke konstruktor biji-bijian dengan atribut terkait [PersistentState("stateName", "providerName")]
. Untuk detail tentang Grain<TState>
, lihat Menggunakan Grain<TState>
untuk menambahkan penyimpanan ke biji berikut ini. Penggunaan Grain<TState>
masih didukung tetapi dianggap sebagai pendekatan warisan.
Mendeklarasikan sebuah kelas untuk menyimpan state elemen biji-bijian Anda:
[Serializable]
public class ProfileState
{
public string Name { get; set; }
public Date DateOfBirth { get; set; }
}
Inject IPersistentState<ProfileState>
ke dalam konstruktor grain:
public class UserGrain : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
public UserGrain(
[PersistentState("profile", "profileStore")]
IPersistentState<ProfileState> profile)
{
_profile = profile;
}
}
Penting
Status profil tidak akan dimuat pada saat disuntikkan ke konstruktor, sehingga mengaksesnya tidak valid pada saat itu. Status akan dimuat sebelum OnActivateAsync dipanggil.
Sekarang setelah biji-bijian memiliki status persisten, Anda dapat menambahkan metode untuk membaca dan menulis status:
public class UserGrain : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
public UserGrain(
[PersistentState("profile", "profileStore")]
IPersistentState<ProfileState> profile)
{
_profile = profile;
}
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
}
Mode kegagalan untuk operasi persistensi
Mode kegagalan untuk operasi baca
Kegagalan yang terjadi pada penyedia penyimpanan selama pembacaan awal data status untuk butir tertentu mengakibatkan kegagalan dalam operasi aktivasi untuk butir tersebut. Dalam kasus seperti itu, tidak akan ada panggilan apa pun ke metode panggilan balik siklus hidup biji-bijian itu OnActivateAsync
. Permintaan asli ke komponen yang menyebabkan kesalahan aktivasi dikembalikan ke pemanggil, sama seperti kegagalan lain selama aktivasi komponen. Kegagalan yang dialami oleh penyedia penyimpanan ketika membaca data status untuk butir tertentu dapat mengakibatkan ReadStateAsync
Task
sebuah pengecualian. Modul dapat memilih untuk menangani atau mengabaikan Task
pengecualian, sama seperti apa pun Task
lainnya di Orleans.
Setiap upaya untuk mengirim pesan ke grain yang gagal dimuat saat permulaan silo karena konfigurasi penyedia penyimpanan yang hilang atau buruk akan mengembalikan kesalahan permanen BadProviderConfigException.
Mode kegagalan pada operasi penulisan
Kegagalan yang dihadapi oleh penyedia penyimpanan saat menulis data status untuk elemen tertentu mengakibatkan pengecualian yang dilemparkan oleh WriteStateAsync()
Task
. Biasanya, ini berarti pengecualian panggilan biji-bijian dilemparkan kembali ke pemanggil klien, asalkan WriteStateAsync()
Task
ditautkan dengan benar ke dalam pengembalian Task
akhir untuk metode biji-bijian ini. Namun, dalam skenario lanjutan tertentu, Anda dapat menulis kode grain secara khusus untuk menangani kesalahan tulis seperti itu, sama seperti menangani kesalahan lainnya Task
.
Unit yang menjalankan penanganan kesalahan atau kode pemulihan harus menangkap pengecualian atau kesalahan WriteStateAsync()
Task
dan tidak melempar ulang, menandakan bahwa mereka telah berhasil menangani kesalahan penulisan.
Rekomendasi
Menggunakan serialisasi JSON atau format serialisasi toleran versi lain
Kode berevolusi, dan ini sering mencakup jenis penyimpanan. Untuk mengakomodasi perubahan ini, konfigurasikan serializer yang sesuai. Untuk sebagian besar penyedia penyimpanan, UseJson
opsi atau serupa tersedia untuk menggunakan JSON sebagai format serialisasi. Pastikan bahwa saat mengembangkan kontrak data, data yang sudah disimpan masih dapat dimuat.
Menggunakan Grain<TState>
untuk menambahkan tempat penyimpanan ke biji-bijian
Penting
Menggunakan Grain<T>
untuk menambahkan penyimpanan ke gandum dianggap fitur lama. Tambahkan penyimpanan biji-bijian menggunakan IPersistentState<T>
seperti yang dijelaskan sebelumnya.
Kelas-kelas yang mewarisi dari Grain<T>
(di mana T
adalah jenis data status khusus untuk aplikasi yang membutuhkan persistensi) akan memiliki status yang dimuat secara otomatis dari penyimpanan yang ditentukan.
Tandai butir tersebut dengan StorageProviderAttribute menentukan instans bernama penyedia penyimpanan yang akan digunakan untuk membaca/menulis data status untuk biji-bijian ini.
[StorageProvider(ProviderName="store1")]
public class MyGrain : Grain<MyGrainState>, /*...*/
{
/*...*/
}
Kelas Grain<T>
dasar menentukan metode berikut untuk subkelas yang akan dipanggil:
protected virtual Task ReadStateAsync() { /*...*/ }
protected virtual Task WriteStateAsync() { /*...*/ }
protected virtual Task ClearStateAsync() { /*...*/ }
Perilaku metode ini sesuai dengan rekan-rekan mereka pada IPersistentState<TState>
yang ditentukan sebelumnya.
Membuat penyedia penyimpanan
Ada dua bagian dari API persistensi status: API yang tersedia untuk grain melalui IPersistentState<T>
atau Grain<T>
, dan API penyedia penyimpanan, yang menekankan pada IGrainStorage
—interface yang harus diimplementasikan oleh penyedia penyimpanan.
/// <summary>
/// Interface to be implemented for a storage able to read and write Orleans grain state data.
/// </summary>
public interface IGrainStorage
{
/// <summary>Read data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">State data object to be populated for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Read operation on the specified grain.</returns>
Task ReadStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
/// <summary>Write data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">State data object to be written for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Write operation on the specified grain.</returns>
Task WriteStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
/// <summary>Delete / Clear data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">Copy of last-known state data object for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Delete operation on the specified grain.</returns>
Task ClearStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
}
/// <summary>
/// Interface to be implemented for a storage able to read and write Orleans grain state data.
/// </summary>
public interface IGrainStorage
{
/// <summary>Read data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">State data object to be populated for this grain.</param>
/// <returns>Completion promise for the Read operation on the specified grain.</returns>
Task ReadStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
/// <summary>Write data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">State data object to be written for this grain.</param>
/// <returns>Completion promise for the Write operation on the specified grain.</returns>
Task WriteStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
/// <summary>Delete / Clear data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">Copy of last-known state data object for this grain.</param>
/// <returns>Completion promise for the Delete operation on the specified grain.</returns>
Task ClearStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
}
Buat penyedia penyimpanan kustom dengan menerapkan antarmuka ini dan mendaftarkan implementasi tersebut. Untuk contoh implementasi penyedia penyimpanan yang ada, lihat AzureBlobGrainStorage
.
Semantik penyedia penyimpanan
Nilai buram khusus penyedia Etag (string
) dapat ditetapkan oleh penyedia penyimpanan sebagai bagian dari metadata status butir yang diisi saat status dibaca. Beberapa penyedia dapat memilih untuk membiarkan ini sebagai null
jika mereka tidak menggunakan Etag
.
Setiap upaya untuk melakukan operasi tulis ketika penyedia penyimpanan mendeteksi pelanggaran batasan Etag
harus menyebabkan penulisan terganggu dengan kesalahan transien Task
dan membungkus pengecualian penyimpanan yang mendasar.
public class InconsistentStateException : OrleansException
{
public InconsistentStateException(
string message,
string storedEtag,
string currentEtag,
Exception storageException)
: base(message, storageException)
{
StoredEtag = storedEtag;
CurrentEtag = currentEtag;
}
public InconsistentStateException(
string storedEtag,
string currentEtag,
Exception storageException)
: this(storageException.Message, storedEtag, currentEtag, storageException)
{
}
/// <summary>The Etag value currently held in persistent storage.</summary>
public string StoredEtag { get; }
/// <summary>The Etag value currently held in memory, and attempting to be updated.</summary>
public string CurrentEtag { get; }
}
Kondisi kegagalan lainnya dari operasi penyimpanan harus menyebabkan yang dikembalikan Task
rusak dengan pengecualian yang menunjukkan masalah penyimpanan yang mendasar. Dalam banyak kasus, pengecualian ini mungkin dilemparkan kembali ke pemanggil yang memulai operasi penyimpanan dengan memanggil metode pada grain. Penting untuk mempertimbangkan apakah penelepon dapat mendeserialisasi pengecualian ini. Misalnya, klien mungkin belum memuat pustaka persistensi tertentu yang berisi jenis pengecualian. Untuk alasan ini, disarankan untuk mengonversi pengecualian menjadi pengecualian yang dapat disebarluaskan kembali ke pemanggil.
Pemetaan data
Penyedia penyimpanan individu harus memutuskan cara terbaik untuk menyimpan status biji-bijian - blob (berbagai format / formulir berseri) atau kolom per bidang adalah pilihan yang jelas.
Mendaftarkan penyedia penyimpanan
Orleans Runtime menyelesaikan penyedia penyimpanan dari penyedia layanan (IServiceProvider) saat butir dibuat. Runtime menentukan instans IGrainStorage. Jika penyedia penyimpanan diberi nama (misalnya, melalui atribut [PersistentState(stateName, storageName)]
), maka instans bernama dari IGrainStorage
akan diselesaikan.
Untuk mendaftarkan instans IGrainStorage
bernama , gunakan AddSingletonNamedService metode ekstensi, ikuti contoh penyedia AzureTableGrainStorage di sini.