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.
Dua bentuk penjadwalan dalam Orleans yang relevan dengan biji-bijian:
- Penjadwalan permintaan: Menjadwalkan panggilan grain masuk untuk eksekusi sesuai dengan aturan yang dibahas dalam Penjadwalan permintaan.
- Penjadwalan Tugas: Menjadwalkan blok kode sinkron untuk dijalankan dengan cara berutas tunggal.
Semua kode pada grain dijalankan pada penjadwal tugas grain, yang berarti permintaan juga dijalankan pada penjadwal tugas grain. Bahkan jika aturan penjadwalan permintaan memungkinkan beberapa permintaan dijalankan secara bersamaan, mereka tidak akan dijalankan secaraparalel karena penjadwal tugas grain selalu menjalankan tugas satu per satu dan tidak pernah menjalankan beberapa tugas secara paralel.
Penjadwalan tugas
Untuk lebih memahami penjadwalan, pertimbangkan butir berikut, MyGrain. Ini memiliki metode yang disebut DelayExecution() yang mencatat pesan, menunggu beberapa waktu, lalu mencatat pesan lain sebelum kembali.
public interface IMyGrain : IGrain
{
Task DelayExecution();
}
public class MyGrain : Grain, IMyGrain
{
private readonly ILogger<MyGrain> _logger;
public MyGrain(ILogger<MyGrain> logger) => _logger = logger;
public async Task DelayExecution()
{
_logger.LogInformation("Executing first task");
await Task.Delay(1_000);
_logger.LogInformation("Executing second task");
}
}
Ketika metode ini dijalankan, isi metode dijalankan dalam dua bagian:
- Panggilan pertama
_logger.LogInformation(...)dan panggilan keTask.Delay(1_000). - Panggilan kedua
_logger.LogInformation(...).
Tugas kedua tidak dijadwalkan pada penjadwal tugas grain hingga Task.Delay(1_000) panggilan selesai. Pada titik itu, ia menjadwalkan kelanjutan metode biji-bijian.
Berikut adalah representasi grafis tentang bagaimana permintaan dijadwalkan dan dijalankan sebagai dua tugas:
Deskripsi di atas tidak spesifik untuk Orleans; ini menjelaskan cara kerja penjadwalan tugas di .NET. Pengompilasi C# mengonversi metode asinkron menjadi mesin status asinkron, dan eksekusi berlangsung melalui mesin status ini dalam langkah-langkah diskrit. Setiap langkah menjadwalkan pada yang saat ini TaskScheduler (diakses melalui TaskScheduler.Current, secara default ke TaskScheduler.Default) atau pada yang saat ini SynchronizationContext. Jika TaskScheduler digunakan, setiap langkah dalam metode mewakili instans Task yang diteruskan ke TaskScheduler tersebut. Oleh karena itu, Task dalam .NET dapat mewakili dua hal konseptual:
- Operasi asinkron yang dapat diantisipasi. Eksekusi metode
DelayExecution()di atas diwakili oleh Task yang dapat menunggu. - Blok kerja yang sinkron. Setiap tahap dalam metode di
DelayExecution()atas diwakili oleh Task.
Ketika TaskScheduler.Default digunakan, kelanjutan dijadwalkan langsung pada .NET ThreadPool dan tidak dibungkus dalam objek Task. Pembungkusan kelanjutan dalam instans Task terjadi secara transparan, sehingga para pengembang jarang perlu menyadari detail-detail implementasi ini.
Penjadwalan tugas di Orleans
Setiap aktivasi butir memiliki TaskScheduler instansnya sendiri yang bertanggung jawab untuk memberlakukan model eksekusi utas tunggal. Secara internal, ini TaskScheduler diimplementasikan melalui ActivationTaskScheduler dan WorkItemGroup.
WorkItemGroup menyimpan tugas antrean dalam Queue<T> (di mana T secara internal adalah Task) dan mengimplementasikan IThreadPoolWorkItem. Untuk mengeksekusi setiap Task yang saat ini diantrekan, WorkItemGroup menjadwalkan dirinya sendiri pada .NET ThreadPool. Ketika .NET ThreadPool memanggil metode WorkItemGroup pada IThreadPoolWorkItem.Execute(), WorkItemGroup mengeksekusi instans Task yang telah diantrekan satu per satu.
Setiap butir memiliki penjadwal yang dijalankan dengan menjadwalkan dirinya sendiri pada .NET ThreadPool:
Setiap penjadwal berisi antrean tugas:
.NET ThreadPool menjalankan setiap item kerja yang diantrekan. Ini termasuk penjadwal biji-bijian serta item kerja lainnya, seperti yang dijadwalkan melalui Task.Run(...):
Nota
Penjadwal grain hanya dapat dijalankan pada satu utas pada satu waktu, tetapi tidak selalu dijalankan pada utas yang sama. .NET ThreadPool dapat bebas menggunakan utas berbeda setiap kali penjadwal grain melakukan eksekusi. Penjadwal grain memastikannya hanya dijalankan secara satu utas pada satu waktu, mengimplementasikan model eksekusi "single-threaded" dari grain.