Bagikan melalui


Mengolah biji-bijian

Sebelum Anda menulis kode untuk mengimplementasikan kelas grain, buat proyek Pustaka Kelas baru yang menargetkan .NET Standard atau .NET Core (lebih disukai) atau .NET Framework 4.6.1 atau yang lebih tinggi (jika Anda tidak dapat menggunakan .NET Standard atau .NET Core karena dependensi). Antarmuka grain dan kelas grain dapat didefinisikan dalam proyek 'Class Library' yang sama, atau dalam dua proyek berbeda untuk pemisahan antarmuka yang lebih baik dari implementasi. Dalam kedua kasus, proyek perlu mereferensikan Microsoft.Orleans. Paket Sdk NuGet.

Untuk petunjuk yang lebih mendetail, lihat bagian Penyiapan Proyek dari Tutorial One – Orleans Dasar-Dasar.

Antarmuka dan kelas biji-bijian

Biji-bijian berinteraksi satu sama lain dan dipanggil dari luar dengan memanggil metode yang dideklarasikan sebagai bagian dari antarmuka biji-bijian masing-masing. Kelas biji-bijian mengimplementasikan satu atau beberapa antarmuka biji-bijian yang dideklarasikan sebelumnya. Semua metode antarmuka butir harus mengembalikan Task (untuk metode void), Task<TResult> atau ValueTask<TResult> (untuk metode yang mengembalikan nilai jenis T).

Berikut ini adalah kutipan dari sampel Orleans Presence Service:

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();

    Task JoinGame(IGameGrain game);

    Task LeaveGame(IGameGrain game);
}

public class PlayerGrain : Grain, IPlayerGrain
{
    private IGameGrain _currentGame;

    // Game the player is currently in. May be null.
    public Task<IGameGrain> GetCurrentGame()
    {
       return Task.FromResult(_currentGame);
    }

    // Game grain calls this method to notify that the player has joined the game.
    public Task JoinGame(IGameGrain game)
    {
       _currentGame = game;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} joined game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
    }

   // Game grain calls this method to notify that the player has left the game.
   public Task LeaveGame(IGameGrain game)
   {
       _currentGame = null;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} left game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
   }
}

Batas waktu respons untuk metode pengolahan grain

Runtime Orleans memungkinkan Anda memberlakukan batas waktu respons per metode grain. Jika metode grain tidak selesai dalam batas waktu, runtime menghasilkan TimeoutException. Untuk memberlakukan batas waktu respons, tambahkan ResponseTimeoutAttribute ke definisi metode butir antarmuka. Sangat penting bahwa atribut ditambahkan ke definisi metode antarmuka, bukan ke implementasi metode di kelas biji-bijian, karena klien dan silo perlu menyadari batas waktu.

Memperluas implementasi PlayerGrain sebelumnya, contoh berikut menunjukkan cara memberlakukan batas waktu respons pada metode LeaveGame:

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();

    Task JoinGame(IGameGrain game);

    [ResponseTimeout("00:00:05")] // 5s timeout
    Task LeaveGame(IGameGrain game);
}

Kode sebelumnya menetapkan batas waktu respons lima detik pada metode LeaveGame. Saat keluar dari permainan, jika membutuhkan waktu lebih dari lima detik, TimeoutException akan diluncurkan.

Mengonfigurasi batas waktu respons

Sama seperti batas waktu respons metode biji-bijian individual, Anda dapat mengonfigurasi batas waktu respons default untuk semua metode biji-bijian. Panggilan ke metode grain akan kedaluwarsa jika respons tidak diterima dalam periode waktu yang ditentukan. Periode ini secara bawaan adalah 30 detik. Anda dapat mengonfigurasi batas waktu respons default:

Untuk informasi selengkapnya tentang mengonfigurasi Orleans, lihat konfigurasi Klien atau konfigurasi Server .

Mengembalikan nilai dari metode grain

Metode grain yang mengembalikan nilai tipe T didefinisikan dalam antarmuka grain sebagai mengembalikan Task<T>. Untuk metode grain yang tidak ditandai dengan kata kunci async, ketika nilai pengembalian tersedia, biasanya dikembalikan melalui pernyataan berikut:

public Task<SomeType> GrainMethod1()
{
    return Task.FromResult(GetSomeType());
}

Metode biji-bijian yang tidak mengembalikan nilai, secara efektif merupakan metode yang batal, didefinisikan dalam antarmuka biji-bijian sebagai mengembalikan Task. Task yang dikembalikan menunjukkan eksekusi asinkron dan penyelesaian metode. Untuk metode yang tidak ditandai dengan kata kunci async, ketika sebuah metode "void" menyelesaikan eksekusinya, ia perlu mengembalikan nilai khusus Task.CompletedTask:

public Task GrainMethod2()
{
    return Task.CompletedTask;
}

Metode butir yang ditandai sebagai async mengembalikan nilai secara langsung:

public async Task<SomeType> GrainMethod3()
{
    return await GetSomeTypeAsync();
}

Metode butir void yang ditandai sebagai async dan tidak mengembalikan nilai akan berhenti setelah eksekusinya selesai.

public async Task GrainMethod4()
{
    return;
}

Jika sebuah metode grain menerima nilai pengembalian dari pemanggilan metode asinkron lain, baik yang ditujukan untuk grain atau bukan, dan tidak perlu melakukan penanganan kesalahan untuk panggilan itu, metode tersebut cukup mengembalikan Task yang diterimanya dari panggilan asinkron tersebut.

public Task<SomeType> GrainMethod5()
{
    Task<SomeType> task = CallToAnotherGrain();

    return task;
}

Demikian pula, metode grain void dapat mengembalikan Task yang diterima kembali melalui panggilan lain tanpa perlu menunggu.

public Task GrainMethod6()
{
    Task task = CallToAsyncAPI();
    return task;
}

ValueTask<T> dapat digunakan alih-alih Task<T>.

Referensi biji-bijian

Referensi Grain adalah objek proxy yang mengimplementasikan antarmuka grain yang sama dengan kelas grain yang sesuai. Ini merangkum identitas logis (jenis dan kunci unik) dari butir target. Referensi grain digunakan untuk melakukan panggilan ke grain target. Setiap referensi biji-bijian adalah untuk satu biji-bijian (satu instans kelas biji-bijian), tetapi seseorang dapat membuat beberapa referensi independen ke biji-bijian yang sama.

Karena referensi biji-bijian mewakili identitas logis dari butir target, itu independen dari lokasi fisik biji-bijian, dan tetap valid bahkan setelah hidupkan ulang sistem secara lengkap. Pengembang dapat menggunakan referensi biji-bijian seperti objek .NET lainnya. Ini dapat diteruskan ke metode, digunakan sebagai nilai pengembalian metode, dll., dan bahkan disimpan ke penyimpanan persisten.

Referensi biji-bijian dapat diperoleh dengan meneruskan identitas biji-bijian ke metode IGrainFactory.GetGrain<TGrainInterface>(Type, Guid), di mana T adalah antarmuka biji-bijian dan key adalah kunci unik dari biji-bijian dalam jenis tersebut.

Berikut adalah contoh untuk memperoleh referensi 'grain' dari antarmuka IPlayerGrain yang ditentukan di atas.

Dari dalam kelas biji-bijian:

IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Dari kode klien Orleans.

IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

Untuk informasi selengkapnya tentang referensi biji-bijian, lihat artikel referensi biji-bijian .

Pemanggilan metode biji-bijian

Model pemrograman Orleans didasarkan pada pemrograman asinkron. Menggunakan referensi "grain" dari contoh sebelumnya, berikut cara melakukan pemanggilan metode "grain":

// Invoking a grain method asynchronously
Task joinGameTask = player.JoinGame(this);

// The await keyword effectively makes the remainder of the
// method execute asynchronously at a later point
// (upon completion of the Task being awaited) without blocking the thread.
await joinGameTask;

// The next line will execute later, after joinGameTask has completed.
players.Add(playerId);

Dimungkinkan untuk menggabungkan dua atau lebih Tasks; operasi penggabungan ini akan menciptakan Task baru yang akan diselesaikan ketika semua Taskbagiannya selesai. Ini adalah pola yang berguna ketika biji-bijian perlu memulai beberapa komputasi dan menunggu semuanya selesai sebelum melanjutkan. Misalnya, modul front-end yang membangun halaman web yang terdiri dari banyak bagian mungkin melakukan beberapa permintaan back-end, satu untuk setiap bagian, dan menerima Task untuk setiap hasil. Biji-bijian kemudian akan menunggu bergabungnya semua Tasksini; ketika gabungan Task diselesaikan, Taskindividu telah selesai, dan semua data yang dibutuhkan untuk memformat halaman web sudah diterima.

Contoh:

List<Task> tasks = new List<Task>();
Message notification = CreateNewMessage(text);

foreach (ISubscriber subscriber in subscribers)
{
    tasks.Add(subscriber.Notify(notification));
}

// WhenAll joins a collection of tasks, and returns a joined
// Task that will be resolved when all of the individual notification Tasks are resolved.
Task joinedTask = Task.WhenAll(tasks);

await joinedTask;

// Execution of the rest of the method will continue
// asynchronously after joinedTask is resolve.

Penyebaran kesalahan

Ketika metode grain menimbulkan pengecualian, Orleans menyebarkan pengecualian tersebut ke atas tumpukan panggilan, di antara host yang berbeda sesuai kebutuhan. Agar ini berfungsi seperti yang dimaksudkan, pengecualian harus dapat diserialisasikan oleh Orleans dan host yang menangani pengecualian harus memiliki jenis pengecualian yang tersedia. Jika jenis pengecualian tidak tersedia, pengecualian akan dilempar sebagai sebuah instans Orleans.Serialization.UnavailableExceptionFallbackException, mempertahankan pesan, jenis, dan jejak tumpukan dari pengecualian asli.

Pengecualian yang dilempar dari metode grain tidak menyebabkan grain dinonaktifkan kecuali pengecualian tersebut mewarisi dari Orleans.Storage.InconsistentStateException. InconsistentStateException dihasilkan oleh operasi penyimpanan ketika menemukan bahwa status dalam memori grain tidak konsisten dengan status dalam database. Selain dari penanganan khusus InconsistentStateException, perilaku ini mirip dengan melemparkan pengecualian dari objek .NET apa pun: pengecualian tidak menyebabkan objek dihancurkan.

Metode virtual

Kelas grain dapat secara opsional mengesampingkan metode virtual OnActivateAsync dan OnDeactivateAsync; metode ini dipanggil oleh runtime Orleans saat aktivasi dan penonaktifan setiap grain dari kelas tersebut. Ini memberi kode grain kesempatan untuk melakukan inisialisasi dan operasi pembersihan tambahan. Pengecualian yang dilemparkan oleh OnActivateAsync menggagalkan proses aktivasi.

Meskipun OnActivateAsync, jika ditimpa atau diganti, selalu dipanggil sebagai bagian dari proses aktivasi grain, OnDeactivateAsync tidak dijamin akan dipanggil dalam semua situasi, misalnya, jika terjadi kegagalan server atau peristiwa abnormal lainnya. Karena itu, aplikasi tidak boleh mengandalkan OnDeactivateAsync untuk melakukan operasi penting seperti persistensi perubahan status. Mereka harus menggunakannya hanya untuk operasi dengan upaya maksimal.

Lihat juga