Freigeben über


Anforderungskontext

Das RequestContext ist ein Orleans-Feature, das es ermöglicht, Anwendungsmetadaten, wie eine Ablaufverfolgungs-ID, zusammen mit Anfragen übertragen zu werden. Sie können Anwendungsmetadaten auf dem Client hinzufügen; diese fließen mit Orleans Anforderungen an das empfangende Grain. Das Feature wird von einer öffentlichen statischen Klasse, RequestContext, im Orleans-Namespace implementiert. Diese Klasse macht zwei einfache Methoden verfügbar:

void Set(string key, object value)

Verwenden Sie die vorherige API, um einen Wert im Anforderungskontext zu speichern. Der Wert kann ein beliebiger serialisierbarer Typ sein.

object Get(string key)

Verwenden Sie die vorherige API, um einen Wert aus dem aktuellen Anforderungskontext abzurufen.

Der Sicherungsspeicher für RequestContext ist asynchron-lokal. Wenn ein Anrufer (clientseitig oder innerhalb Orleans) eine Anforderung sendet, werden die Inhalte des Anrufers RequestContext in die Orleans-Nachricht für die Anforderung einbezogen. Wenn der Korncode die Anforderung empfängt, kann auf diese Metadaten über die lokale Datei RequestContextzugegriffen werden. Wenn der Korncode den RequestContextCode nicht ändert, empfängt jedes Korn, das er anfordert, die gleichen Metadaten usw.

Anwendungsmetadaten werden auch beibehalten, wenn Sie eine zukünftige Berechnung mithilfe von StartNew oder ContinueWith planen. In beiden Fällen wird die Fortsetzung mit denselben Metadaten wie der Planungscode ausgeführt, als die Berechnung geplant wurde. Das heißt, das System kopiert die aktuellen Metadaten und übergibt sie an die Fortsetzung, sodass die Fortsetzung keine Änderungen sieht, die nach dem Aufruf von StartNew oder ContinueWith vorgenommen wurden.

Wichtig

Anwendungsmetadaten fließen nicht mit Antworten zurück. Code, der als Ergebnis des Empfangens einer Antwort (entweder innerhalb einer ContinueWith Fortsetzung oder nach einem Aufruf Task.Wait() oder GetValue) ausgeführt wird, wird weiterhin innerhalb des aktuellen Kontexts ausgeführt, der von der ursprünglichen Anforderung festgelegt wurde.

Um beispielsweise eine Ablaufverfolgungs-ID im Client auf einen neuen Guid zu setzen, rufen Sie auf:

RequestContext.Set("TraceId", Guid.NewGuid());

Innerhalb des Grain-Codes (oder eines anderen Codes, der auf einem Planer-Thread Orleans ausgeführt wird), können Sie die Ablaufverfolgungs-ID der ursprünglichen Clientanforderung verwenden, z. B. beim Protokollieren:

Logger.LogInformation(
    "Currently processing external request {TraceId}",
    RequestContext.Get("TraceId"));

Sie können zwar eine beliebige serialisierbare object Datei als Anwendungsmetadaten senden, aber es empfiehlt sich, darauf hinzuweisen, dass große oder komplexe Objekte einen spürbaren Mehraufwand für die Serialisierungszeit von Nachrichten verursachen können. Aus diesem Grund wird empfohlen, einfache Typen (Zeichenfolgen, GUIDs oder numerische Typen) zu verwenden.

Beispielcode für Korn

Um die Verwendung des Anforderungskontexts zu veranschaulichen, betrachten Sie den folgenden Beispiel-Code:

using GrainInterfaces;
using Microsoft.Extensions.Logging;

namespace Grains;

public class HelloGrain(ILogger<HelloGrain> logger) : Grain, IHelloGrain
{
    ValueTask<string> IHelloGrain.SayHello(string greeting)
    {
        _logger.LogInformation("""
            SayHello message received: greeting = "{Greeting}"
            """,
            greeting);
        
        var traceId = RequestContext.Get("TraceId") as string 
            ?? "No trace ID";

        return ValueTask.FromResult($"""
            TraceID: {traceId}
            Client said: "{greeting}", so HelloGrain says: Hello!
            """);
    }
}

public interface IHelloGrain : IGrainWithStringKey
{
    ValueTask<string> SayHello(string greeting);
}

Die SayHello Methode protokolliert den eingehenden greeting Parameter und ruft dann die Trace ID aus dem Anforderungskontext ab. Wenn keine Ablaufverfolgungs-ID gefunden wird, protokolliert das Korn "Keine Ablaufverfolgungs-ID".

Beispiel für Clientcode

Der Client kann die Ablaufverfolgungs-ID im Anforderungskontext festlegen, bevor die SayHello Methode für die HelloGrain aufgerufen wird. Der folgende Clientcode veranschaulicht, wie eine Ablaufverfolgungs-ID im Anforderungskontext festgelegt und die Methode SayHello auf dem HelloGrain aufgerufen wird.

using GrainInterfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

using var host = Host.CreateDefaultBuilder(args)
    .UseOrleansClient(clientBuilder =>
        clientBuilder.UseLocalhostClustering())
    .Build();

await host.StartAsync();

var client = host.Services.GetRequiredService<IClusterClient>();

var grain = client.GetGrain<IHelloGrain>("friend");

var id = "example-id-set-by-client";

RequestContext.Set("TraceId", id);

var message = await friend.SayHello("Good morning!");

Console.WriteLine(message);
// Output:
//   TraceID: example-id-set-by-client
//   Client said: "Good morning!", so HelloGrain says: Hello!

In diesem Beispiel legt der Client die Ablaufverfolgungs-ID auf "example-id-set-by-client" fest, bevor er die Methode mit SayHello auf der HelloGrain aufruft. Das Korn ruft die Ablaufverfolgungs-ID aus dem Anforderungskontext ab und protokolliert sie.