Werkstroomuitvoeringsmodi

Wanneer u een werkstroom uitvoert in .NET, bepaalt de uitvoeringsmodus hoe supersteps worden verwerkt en hoe gebeurtenissen aan de consument worden geleverd. De InProcessExecution klasse bevat twee uitvoeringsmodi: OffThread en Lockstep.

Overzicht

OffThread (standaard) Lockstep
Superstep-uitvoering Achtergrondproces Thread van de consument
Levering van gebeurtenissen Onmiddellijk, wanneer er gebeurtenissen worden vermeld Gegroepeerd nadat elke superstep is voltooid
Stap uitvoering Onafhankelijk van gebeurtenisverwerking Gepauzeerd totdat batchgebeurtenissen worden verwerkt
concurrentie Consument leest gebeurtenissen terwijl supersteps worden uitgevoerd De uitvoering van consument en superstep wisselen elkaar af
Het beste voor Realtime streaming, productiescenario's Testen, foutopsporing, deterministische volgorde

OffThread

OffThread is de standaarduitvoeringsmodus . Supersteps worden uitgevoerd op een achtergrondthread en gebeurtenissen worden onmiddellijk uitgestroomd wanneer ze worden gegenereerd via een implementatie op basis van kanalen.

// OffThread is the default — these are equivalent:
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input);
await using StreamingRun run = await InProcessExecution.OffThread.RunStreamingAsync(workflow, input);

Hoe werkt het?

  1. Een achtergrondtaak voert continu supersteps uit terwijl berichten in de wachtrij staan.
  2. Wanneer uitvoerders uitvoer of gebeurtenissen opleveren, worden de resulterende WorkflowEvent objecten naar een niet-gebonden Channel<WorkflowEvent>object geschreven.
  3. De consument leest gebeurtenissen van het kanaal via WatchStreamAsync, die ze in realtime ontvangt terwijl ze worden geproduceerd.
  4. Wanneer alle supersteps zijn voltooid en er geen berichten meer zijn, wordt de uitvoering gestopt met een Idle of PendingRequests status.

Omdat de superstep-lus en de consumer tegelijk draaien, verschijnen gebeurtenissen direct zodra ze worden gegenereerd zonder enige buffervertraging. Dit maakt OffThread ideaal voor streamingscenario's waarbij het leveren van gebeurtenissen met lage latentie belangrijk is, zoals het weergeven van token-by-token-updates in een gebruikersinterface.

Gelijktijdige uitvoeringen

OffThread ondersteunt ook een gelijktijdige variant waarmee meerdere uitvoeringen tegelijkertijd hetzelfde werkstroomexemplaren kunnen delen:

await using StreamingRun run = await InProcessExecution.Concurrent.RunStreamingAsync(workflow, input);

Belangrijk

Gelijktijdige uitvoering vereist dat alle uitvoerders in de werkstroom worden gedeclareerd crossRunShareable (op de constructor) of als fabrieksmethoden worden geleverd.

Lockstep

In de Lockstep-modus worden supersteps uitgevoerd in de thread van de consument in plaats van op een achtergrondtaak. Gebeurtenissen worden verzameld tijdens elke superstep en verzonden als een batch nadat de superstep is voltooid.

await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, input);

Hoe werkt het?

  1. De consument roept WatchStreamAsyncaan, die de uitvoeringslus aanstuurt.
  2. Een superstap wordt uitgevoerd tot voltooiing en gebeurtenissen worden verzameld in een wachtrij.
  3. Nadat de superstap is voltooid, worden alle gebeurtenissen in de wachtrij aan de consument overgedragen.
  4. De volgende superstep begint pas nadat de consument alle gebeurtenissen van de vorige superstep heeft ontvangen.

Dit afwisselende patroon betekent dat de verbruiker en de workflow-engine nooit tegelijkertijd worden uitgevoerd. Levering van gebeurtenissen is deterministisch: alle gebeurtenissen van een superstep worden gegarandeerd geleverd voordat gebeurtenissen van de volgende superstep binnenkomen.

Wanneer gebruikt u Lockstep?

Lockstep is handig wanneer:

  • Testen : deterministische volgorde van gebeurtenissen maakt asserties eenvoudig.
  • Foutopsporing: stapsgewijze foutopsporing is eenvoudiger wanneer de uitvoering op de thread van de consument blijft staan.
  • Geordende verwerking : scenario's waarin u de gebeurtenissen van één superstep volledig moet verwerken voordat de volgende superstep begint.

Een uitvoeringsmodus kiezen

Voor de meeste productiescenario's wordt de standaardmodus OffThread aanbevolen. Het biedt de beste reactiesnelheid en stelt de werkstroom in staat om door te gaan met verwerken terwijl de consument gebeurtenissen verwerkt.

Gebruik Lockstep wanneer deterministisch gedrag belangrijker is dan prestaties, zoals in eenheidstests of foutopsporingssessies.

// Production: OffThread (default)
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, input);

// Testing: Lockstep for deterministic behavior
await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, input);

Uitvoering van niet-streaming

Beide uitvoeringsmodi ondersteunen niet-streaming-uitvoering via RunAsync. In de niet-streamingmodus wordt de workflow uitgevoerd tot aan voltooiing en worden alle gebeurtenissen in een Run object verzameld in plaats van deze stapsgewijs te streamen.

Run run = await InProcessExecution.RunAsync(workflow, input);

// Access all emitted events
foreach (WorkflowEvent evt in run.OutgoingEvents)
{
    // Process events
}

Omdat niet-streaming-uitvoering alle gebeurtenissen na voltooiing verzamelt, is het voordeel van de levering van gebeurtenissen in realtime van OffThread niet van toepassing. Het belangrijkste verschil tussen modi in niet-streamingscenario's is threading: OffThread voert supersteps uit op een achtergrondthread, waardoor de aanroepende thread wordt vrijgemaakt terwijl wordt gewacht op voltooiing, terwijl Lockstep supersteps uitvoert op de thread van de beller, waardoor deze wordt geblokkeerd totdat de werkstroom is voltooid.

Uitvoering van niet-streaming gebruikt de standaardmodus OffThread. Lockstep gebruiken met niet-streaming-uitvoering:

Run run = await InProcessExecution.Lockstep.RunAsync(workflow, input);

Volgende stappen 

Uitvoeringsmodi zijn niet van toepassing op Python-werkstromen. Python-werkstromen maken gebruik van één uitvoeringsmodel dat superstepverwerking en gebeurtenislevering verwerkt via een asynchrone generator. Dit model is vergelijkbaar met de .NET Lockstep-modus. Stappen gaan niet verder, tenzij de consument actief gebeurtenissen uit de generator haalt.

Zie Workflow Builder & Execution voor meer informatie over het uitvoeren van Python-werkstromen.

Wanneer u een werkstroom uitvoert in Go, bepaalt de uitvoeringsomgeving hoe supersteps worden verwerkt en hoe gebeurtenissen aan de consument worden geleverd. Het workflow/inproc pakket bevat drie omgevingen: Default/OffThread, Lockstepen .Concurrent

Overzicht

OffThread / Standaard Lockstep Gelijktijdig
Superstep-uitvoering Achtergrondroutine Aangestuurd door de gebeurtenisconsumer Achtergrondroutine
Levering van gebeurtenissen Onmiddellijk, wanneer er gebeurtenissen worden vermeld In batches verwerkt terwijl de stream wordt verwerkt Onmiddellijk, wanneer er gebeurtenissen worden vermeld
Het beste voor Realtime streaming, productiescenario's Testen, foutopsporing, deterministische volgorde Gedeelde werkstroomexemplaren met gelijktijdige veilige bindingen

OffThread

OffThread is de standaarduitvoeringsmodus. Dit zijn equivalent:

stream, err := inproc.Default.RunStreaming(ctx, wf, input)
stream, err := inproc.OffThread.RunStreaming(ctx, wf, input)

Hoe werkt het?

  1. Met een achtergrondroutine worden supersteps uitgevoerd terwijl berichten in behandeling zijn.
  2. Wanneer executors resultaten of gebeurtenissen opleveren, worden workflowgebeurtenissen weggeschreven naar de stream.
  3. De consument leest gebeurtenissen met WatchStreamen ontvangt ze wanneer ze worden geproduceerd.
  4. Wanneer alle supersteps zijn voltooid en er geen berichten meer over zijn, stopt de uitvoering met een inactieve status of een wachtende-aanvraagstatus.

Gelijktijdige uitvoeringen

Gebruiken inproc.Concurrent wanneer alle uitvoerdersbindingen in de werkstroom gelijktijdige gedeelde uitvoering ondersteunen:

stream, err := inproc.Concurrent.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

Lockstep

In de Lockstep-modus vordert de uitvoering van de workflow naarmate de afnemer uit de stream leest. Dit maakt gebeurtenisvolgorde deterministisch voor tests en foutopsporing.

stream, err := inproc.Lockstep.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

for evt, err := range stream.WatchStream(ctx) {
    if err != nil {
        return err
    }
    // inspect event
}

Hoe werkt het?

  1. De consument roept WatchStreamaan, die de uitvoeringslus aanstuurt.
  2. Een superstep wordt volledig uitgevoerd en gebeurtenissen worden geaccumuleerd.
  3. De verzamelde gebeurtenissen worden aan de afnemer geleverd.
  4. De volgende superstep begint pas nadat de consument de gebeurtenissen van de vorige superstep heeft ontvangen.

Wanneer gebruikt u Lockstep?

Gebruik Lockstep wanneer deterministisch gedrag meer belangrijk is dan streaming met lage latentie, zoals eenheidstests, foutopsporing of scenario's waarin u de gebeurtenissen van één superstep volledig wilt verwerken voordat de volgende superstep begint.

Een uitvoeringsmodus kiezen

Gebruik voor de meeste productiescenario’s inproc.Default of inproc.OffThread. Gebruik inproc.Lockstep deze functie wanneer deterministische volgorde van gebeurtenissen belangrijker is dan streaminglatentie, zoals in tests. Alleen gebruiken inproc.Concurrent wanneer elke binding in de werkstroom gelijktijdige gedeelde uitvoering ondersteunt.

// Production: OffThread (default)
stream, err := inproc.Default.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer stream.Close(ctx)

// Testing: Lockstep for deterministic behavior
testStream, err := inproc.Lockstep.RunStreaming(ctx, wf, input)
if err != nil {
    return err
}
defer testStream.Close(ctx)

Uitvoering van niet-streaming

Alle uitvoeringsomgevingen ondersteunen ook niet-streaming Run, waarbij de uitvoering doorgaat tot de volgende onderbreking en de gegenereerde gebeurtenissen in de geretourneerde uitvoering worden opgeslagen.

run, err := inproc.Default.Run(ctx, wf, input)
if err != nil {
    return err
}

for evt := range run.NewEvents() {
    if output, ok := evt.(workflow.OutputEvent); ok {
        fmt.Printf("Final result: %v\n", output.Output)
    }
}

Volgende stappen