Sdílet prostřednictvím


Přehled plánování

Existují dvě formy plánování, ve Orleans kterých jsou relevantní pro zrnka:

  1. Plánování požadavků, plánování příchozích volání agregace pro provádění podle pravidel plánování probíraných v plánování požadavků.
  2. Plánování úloh, plánování synchronních bloků kódu, které se mají spouštět jedním vláknem

Veškerý kód agregačního intervalu se provádí v plánovači úloh agregačního intervalu, což znamená, že požadavky se také provádějí v plánovači úloh odstupňovaného intervalu. I když pravidla plánování požadavků umožňují souběžné provádění více požadavků, nespustí se paralelně, protože plánovač úloh agregačního procesu vždy provádí úkoly 1 po druhém, a proto nikdy nespustí více úkolů paralelně.

Plánování úkolů

Pokud chcete lépe porozumět plánování, zvažte následující agregační interval, MyGrainkterý má metodu, která protokoluje DelayExecution() zprávu, chvíli počká a pak před vrácením zaprokoluje další zprávu.

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

Při spuštění této metody se tělo metody spustí ve dvou částech:

  1. První _logger.LogInformation(...) hovor a volání na Task.Delay(1_000).
  2. Druhý _logger.LogInformation(...) hovor.

Druhý úkol nebude naplánován na plánovač úloh odstupňovaného plánu, dokud Task.Delay(1_000) se volání nedokončí, v jakém okamžiku naplánuje pokračování metody agregace.

Tady je grafické znázornění toho, jak je požadavek naplánován a proveden jako dva úkoly:

Two-Task-based request execution example.

Výše uvedený popis není specifický Orleans pro plánování úkolů v rozhraní .NET: asynchronní metody v jazyce C# se převedou na asynchronní stavový počítač kompilátorem a prováděním probíhá prostřednictvím asynchronního stavového počítače v diskrétních krocích. Každý krok je naplánován na aktuální TaskScheduler (přístup prostřednictvím TaskScheduler.Current, výchozí nastavení TaskScheduler.Default) nebo aktuální SynchronizationContext. Pokud se používá, TaskScheduler každý krok v metodě je reprezentován Task instancí, která je předána této TaskScheduler. Proto může . Task NET představovat dvě koncepční věci:

  1. Asynchronní operace, na kterou lze čekat. Výše uvedená DelayExecution() metoda je reprezentována metodou Task , kterou lze očekávat.
  2. V synchronním bloku práce je každá fáze výše DelayExecution() uvedené metody reprezentována Task.

Při TaskScheduler.Default použití jsou pokračování naplánována přímo na .NET ThreadPool a nejsou zabaleny do objektu Task . Obtékání pokračování v Task instancích probíhá transparentně, a proto vývojáři zřídka potřebují vědět o těchto podrobnostech implementace.

Plánování úkolů v Orleans

Každá aktivace zrnitosti má vlastní TaskScheduler instanci, která je zodpovědná za vynucování modelu provádění s jedním vláknem zrn. Interně se to TaskScheduler implementuje prostřednictvím ActivationTaskScheduler a WorkItemGroup. WorkItemGroup udržuje zařazení úkolů do fronty v Queue<T> místě, kde T je Task interně a implementuje IThreadPoolWorkItem. Chcete-li spustit jednotlivé aktuálně spuštěné fronty Task, WorkItemGroup naplánuje se v rozhraní .NET ThreadPool. Když .NET ThreadPool vyvolá metodu WorkItemGroup's IThreadPoolWorkItem.Execute() , WorkItemGroup spustí vyčtené Task instance 1-1.

Každý agregační interval má plánovač, který se provádí naplánováním samotného na platformě .NET ThreadPool:

Orleans grains scheduling themselves on the .NET ThreadPool.

Každý plánovač obsahuje frontu úloh:

Scheduler queue of scheduled tasks.

.NET ThreadPool spustí každou pracovní položku, která se do ní začtou. To zahrnuje plánovače podrobností a také další pracovní položky, jako jsou pracovní položky naplánované prostřednictvím Task.Run(...):

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

Poznámka:

Plánovač agregačního intervalu se může spustit pouze na jednom vlákně najednou, ale ne vždy se provádí ve stejném vlákně. .NET ThreadPool je zdarma používat jiné vlákno při každém spuštění plánovače agregačního intervalu. Plánovač agregace je zodpovědný za to, že se provádí pouze na jednom vlákně najednou a tímto způsobem se implementuje model provádění zrn s jedním vláknem.