Condividi tramite


Contesto della richiesta

RequestContext è una Orleans funzionalità che consente ai metadati dell'applicazione, ad esempio un ID di traccia, di fluire con le richieste. I metadati dell'applicazione possono essere aggiunti nel client; scorrerà con le richieste Orleans al livello di granularità di ricezione. La funzionalità viene implementata da una classe statica pubblica, RequestContext, nello spazio dei nomi Orleans. Questa classe espone due metodi semplici:

void Set(string key, object value)

L'API precedente viene usata per archiviare un valore nel contesto della richiesta. Il valore può essere qualsiasi tipo serializzabile.

object Get(string key)

L'API precedente viene usata per recuperare un valore dal contesto di richiesta corrente.

L'archiviazione di backup per RequestContext è asincrona locale. Quando un chiamante (lato client o all'interno di Orleans) invia una richiesta, il contenuto di RequestContext del chiamante viene incluso nel messaggio Orleans per la richiesta; quando il codice granulare riceve la richiesta, i metadati sono accessibili da RequestContext locale. Se il codice granulare non modifica il RequestContext, qualsiasi granularità a cui fa richiesta riceverà gli stessi metadati e così via.

I metadati dell'applicazione vengono mantenuti anche quando si pianifica un calcolo futuro usando StartNew o ContinueWith. In entrambi i casi, la continuazione verrà eseguita con gli stessi metadati del codice di pianificazione nel momento in cui il calcolo è stato pianificato, ovvero il sistema crea una copia dei metadati correnti e lo passa alla continuazione, quindi le modifiche dopo la chiamata a StartNew o ContinueWith non verranno visualizzate dalla continuazione.

Importante

I metadati dell'applicazione non vengono restituiti con risposte; ovvero, il codice eseguito come risultato della ricezione di una risposta, all'interno di una continuazione ContinueWith o dopo una chiamata a Task.Wait() o GetValue, verrà comunque eseguito all'interno del contesto corrente impostato dalla richiesta originale.

Ad esempio, per impostare un ID di traccia nel client su un nuovo Guidoggetto , chiamare:

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

All'interno del codice granulare (o di altro codice eseguito all'interno di Orleans in un thread dell'utilità di pianificazione), è possibile usare l'ID di traccia della richiesta client originale, ad esempio durante la scrittura di un log:

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

Anche se qualsiasi serializzabile object può essere inviato come metadati dell'applicazione, vale la pena ricordare che gli oggetti di grandi dimensioni o complessi possono aggiungere un sovraccarico notevole al tempo di serializzazione dei messaggi. Per questo motivo, è consigliabile usare tipi semplici (stringhe, GUID o tipi numerici).

Codice granulare di esempio

Per illustrare l'uso di un contesto di richiesta, prendere in considerazione il codice granulare di esempio seguente:

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

Il SayHello metodo registra il parametro in ingresso greeting e quindi recupera l'ID di traccia dal contesto della richiesta. Se non viene trovato alcun ID di traccia, i log granulari "Nessun ID traccia".

Codice client di esempio

Il client è in grado di impostare l'ID di traccia nel contesto della richiesta prima di chiamare il SayHello metodo su HelloGrain. Il codice client seguente illustra come impostare un ID di traccia nel contesto della richiesta e chiamare il SayHello metodo in HelloGrain:

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 questo esempio, il client imposta l'ID di traccia su "example-id-set-by-client" prima di chiamare il SayHello metodo su HelloGrain. La granularità recupera l'ID di traccia dal contesto della richiesta e lo registra.