Udostępnij za pośrednictwem


Omówienie planowania

Istnieją dwie formy planowania, w Orleans których są istotne dla ziarna:

  1. Planowanie żądań, planowanie przychodzących wywołań ziarna do wykonania zgodnie z regułami planowania omówionymi w temacie Planowanie żądań.
  2. Planowanie zadań, planowanie synchronicznych bloków kodu do wykonania w sposób jednowątkowy

Cały kod ziarna jest wykonywany w harmonogramie zadań ziarna, co oznacza, że żądania są również wykonywane w harmonogramie zadań ziarna. Nawet jeśli reguły planowania żądań zezwalają na współbieżne wykonywanie wielu żądań, nie będą one wykonywane równolegle, ponieważ harmonogram zadań ziarna zawsze wykonuje zadania jeden po jednym i dlatego nigdy nie wykonuje wielu zadań równolegle.

Planowanie zadań

Aby lepiej zrozumieć planowanie, rozważ następujące ziarno, MyGrainktóre ma metodę o nazwie DelayExecution() , która rejestruje komunikat, czeka trochę czasu, a następnie rejestruje kolejny komunikat przed zwróceniem.

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");
    }
}

Po wykonaniu tej metody treść metody zostanie wykonana w dwóch częściach:

  1. Pierwsze _logger.LogInformation(...) wywołanie i wywołanie metody .Task.Delay(1_000)
  2. Drugie _logger.LogInformation(...) wywołanie.

Drugie zadanie nie zostanie zaplanowane zgodnie z harmonogramem zadań ziarna, dopóki Task.Delay(1_000) wywołanie nie zostanie zakończone, w którym momencie zaplanuje kontynuację metody ziarna.

Oto graficzna reprezentacja sposobu planowania i wykonywania żądania jako dwóch zadań:

Two-Task-based request execution example.

Powyższy opis nie jest specyficzny dla Orleans funkcji planowania zadań na platformie .NET: metody asynchroniczne w języku C# są konwertowane na maszynę stanu asynchronicznego przez kompilator i wykonywanie postępuje przez maszynę stanu asynchronicznego w dyskretnych krokach. Każdy krok jest zaplanowany dla bieżącego TaskScheduler (dostępnego za pośrednictwem TaskScheduler.Current, domyślnie na TaskScheduler.Default) lub bieżącego SynchronizationContext. TaskScheduler Jeśli element jest używany, każdy krok w metodzie jest reprezentowany przez Task wystąpienie, które jest przekazywane do tego TaskSchedulerelementu . W związku z tym element na Task platformie .NET może reprezentować dwie koncepcje:

  1. Operacja asynchroniczna, którą można zaczekać. Wykonanie powyższej DelayExecution() metody jest reprezentowane przez Task element, którego można oczekiwać.
  2. W synchronicznym bloku pracy każdy etap w DelayExecution() powyższej metodzie jest reprezentowany przez Taskelement .

Gdy TaskScheduler.Default jest w użyciu, kontynuacje są zaplanowane bezpośrednio na platformie .NET ThreadPool i nie są opakowane w Task obiekt. Zawijanie kontynuacji w Task wystąpieniach odbywa się w sposób niewidoczny i dlatego deweloperzy rzadko muszą być świadomi tych szczegółów implementacji.

Planowanie zadań w programie Orleans

Każda aktywacja ziarna ma własne TaskScheduler wystąpienie, które jest odpowiedzialne za wymuszanie modelu wykonywania jednowątkowego ziarna. Wewnętrznie jest to TaskScheduler implementowane za pośrednictwem metod ActivationTaskScheduler i WorkItemGroup. WorkItemGroup program przechowuje zadania w kolejce w miejscu Queue<T> , gdzie T jest Task wewnętrznie i implementuje IThreadPoolWorkItem. Aby wykonać każdą aktualnie w kolejce Task, WorkItemGroup harmonogramy są wykonywane na platformie .NET ThreadPool. Gdy platforma .NET ThreadPool wywołuje WorkItemGroupmetodę "s IThreadPoolWorkItem.Execute() ", WorkItemGroup funkcja wykonuje w kolejce Task wystąpienia jeden po jednym.

Każde ziarno ma harmonogram, który jest wykonywany przez zaplanowanie się na platformie .NET ThreadPool:

Orleans grains scheduling themselves on the .NET ThreadPool.

Każdy harmonogram zawiera kolejkę zadań:

Scheduler queue of scheduled tasks.

Platforma .NET ThreadPool wykonuje każdy element roboczy w kolejce. Obejmuje to harmonogramy ziarna, a także inne elementy robocze, takie jak elementy robocze zaplanowane za pomocą polecenia Task.Run(...):

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

Uwaga

Harmonogram ziarna może być wykonywany tylko w jednym wątku jednocześnie, ale nie zawsze jest wykonywany w tym samym wątku. Platforma .NET ThreadPool może używać innego wątku za każdym razem, gdy harmonogram ziarna jest wykonywany. Harmonogram ziarna jest odpowiedzialny za upewnienie się, że wykonuje tylko jeden wątek w danym momencie i tak jest implementowany model wykonywania pojedynczego wątku ziarna.