Bagikan melalui


Gambaran umum penjadwalan

Ada dua bentuk penjadwalan Orleans yang relevan dengan biji-bijian:

  1. Minta penjadwalan, penjadwalan panggilan grain masuk untuk eksekusi sesuai dengan aturan penjadwalan yang dibahas dalam Penjadwalan permintaan.
  2. Penjadwalan tugas, penjadwalan blok kode sinkron yang akan dijalankan dengan cara satu utas

Semua kode biji-bijian dijalankan pada penjadwal tugas grain, yang berarti bahwa permintaan juga dijalankan pada penjadwal tugas grain. Bahkan jika aturan penjadwalan permintaan memungkinkan beberapa permintaan untuk dijalankan secara bersamaan, mereka tidak akan menjalankan secara paralel karena penjadwal tugas grain selalu menjalankan tugas satu per satu dan karenanya tidak pernah menjalankan beberapa tugas secara paralel.

Penjadwalan tugas

Untuk lebih memahami penjadwalan, pertimbangkan butir berikut, MyGrain, yang memiliki metode yang memanggil DelayExecution() log 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 akan dijalankan dalam dua bagian:

  1. Panggilan pertama _logger.LogInformation(...) dan panggilan ke Task.Delay(1_000).
  2. Panggilan kedua _logger.LogInformation(...) .

Tugas kedua tidak akan dijadwalkan pada penjadwal tugas grain sampai Task.Delay(1_000) panggilan selesai, di mana ia akan menjadwalkan kelanjutan metode biji-bijian.

Berikut adalah representasi grafis tentang bagaimana permintaan dijadwalkan dan dijalankan sebagai dua tugas:

Two-Task-based request execution example.

Deskripsi di atas tidak spesifik untuk Orleans dan adalah bagaimana penjadwalan tugas dalam .NET bekerja: metode asinkron di C# dikonversi menjadi mesin status asinkron oleh kompilator dan eksekusi berlangsung melalui komputer status asinkron dalam langkah-langkah diskrit. Setiap langkah dijadwalkan pada saat ini TaskScheduler (diakses melalui TaskScheduler.Current, default ke TaskScheduler.Default) atau saat ini SynchronizationContext. TaskScheduler Jika sedang digunakan, setiap langkah dalam metode diwakili oleh Task instans yang diteruskan ke TaskScheduler. Oleh karena itu, Task dalam .NET dapat mewakili dua hal konseptual:

  1. Operasi asinkron yang dapat ditunggu. Eksekusi metode di DelayExecution() atas diwakili oleh Task yang dapat ditunggu.
  2. Dalam blok pekerjaan yang sinkron, setiap tahap dalam metode di DelayExecution() atas diwakili oleh Task.

Ketika TaskScheduler.Default sedang digunakan, kelanjutan dijadwalkan langsung ke .NET ThreadPool dan tidak dibungkus dalam Task objek. Pembungkusan kelanjutan dalam Task instans terjadi secara transparan dan oleh karena itu pengembang jarang perlu mengetahui detail implementasi ini.

Penjadwalan tugas di Orleans

Setiap aktivasi biji-bijian memiliki instans sendiri TaskScheduler yang bertanggung jawab untuk memberlakukan model eksekusi satu utas biji-bijian. Secara internal, ini TaskScheduler diimplementasikan melalui ActivationTaskScheduler dan WorkItemGroup. WorkItemGroup menyimpan tugas antrean di Queue<T> tempat T adalah Task secara internal dan mengimplementasikan IThreadPoolWorkItem. Untuk menjalankan masing-masing yang saat ini diantrekan Task, WorkItemGroup jadwalkan sendiri pada .NET ThreadPool. Ketika .NET ThreadPool memanggil WorkItemGroupmetode 's IThreadPoolWorkItem.Execute() , WorkItemGroup menjalankan instans antrean Task satu per satu.

Setiap butir memiliki penjadwal yang dijalankan dengan menjadwalkan dirinya sendiri pada .NET ThreadPool:

Orleans grains scheduling themselves on the .NET ThreadPool.

Setiap penjadwal berisi antrean tugas:

Scheduler queue of scheduled tasks.

.NET ThreadPool menjalankan setiap item kerja yang diantrekan. Ini termasuk penjadwal biji-bijian serta item kerja lainnya, seperti item kerja yang dijadwalkan melalui Task.Run(...):

Visualization of the all schedulers running in the .NET ThreadPool.

Catatan

Penjadwal grain hanya dapat dijalankan pada satu utas pada satu waktu, tetapi tidak selalu dijalankan pada utas yang sama. .NET ThreadPool bebas menggunakan utas yang berbeda setiap kali penjadwal grain dijalankan. Penjadwal grain bertanggung jawab untuk memastikan bahwa itu hanya dijalankan pada satu utas pada satu waktu dan ini adalah bagaimana model eksekusi satu utas biji-bijian diimplementasikan.