Partager via


Contexte de demandes

RequestContext est une fonctionnalité d’Orleans qui permet aux métadonnées d’application, telles qu’un ID de trace, d’accompagner les demandes. Les métadonnées d’application peuvent être ajoutées au niveau du client ; elles accompagneront les demandes Orleans jusqu’au grain de destination. La fonctionnalité est implémentée par une classe statique publique, RequestContext, dans l’espace de noms Orleans. Cette classe expose deux méthodes simples :

void Set(string key, object value)

L’API précédente sert à stocker une valeur dans le contexte de la demande. La valeur peut être de n’importe quel type sérialisable.

object Get(string key)

L’API précédente sert à récupérer une valeur du contexte de demande actuel.

Le stockage de sauvegarde pour RequestContext est un stockage local asynchrone. Quand un appelant (qu’il soit côté client ou dans Orleans) envoie une requête, le contenu du RequestContext de l’appelant est inclus avec le message Orleans pour la requête ; quand le code de grain reçoit la requête, ces métadonnées sont accessibles à partir du RequestContext local. Si le code de grain ne modifie pas le RequestContext, tout grain qui le demande recevra les mêmes métadonnées, et ainsi de suite.

Les métadonnées d’application sont également conservées quand vous planifiez un calcul à venir à l’aide de StartNew ou ContinueWith ; dans les deux cas, la continuation s’exécutera avec les mêmes métadonnées dont le code de planification disposait au moment où le calcul a été planifié (autrement dit, le système effectue une copie des métadonnées actuelles et les transmet à la continuation, si bien que les modifications postérieures à l’appel à StartNew ou ContinueWith ne seront pas vues par la continuation).

Important

Les métadonnées d’application ne sont pas retournées en même temps que les réponses ; autrement dit, le code qui s’exécute par suite d’une réponse reçue, que ce soit dans une continuation ContinueWith ou après un appel à Task.Wait() ou GetValue, continuera de s’exécuter dans le contexte actuel qui a été défini par la demande d’origine.

Par exemple, pour définir un ID de trace dans le client sur un nouveau Guid, vous appelez :

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

Dans le code de grain (ou dans tout autre code qui s’exécute dans Orleans sur un thread de planificateur), l’ID de trace de la requête cliente d’origine peut être utilisé, par exemple, lors de l’écriture d’un journal :

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

Bien que toute sérialisable object puisse être envoyée en tant que métadonnées d’application, il est important de mentionner que les objets volumineux ou complexes peuvent ajouter une surcharge notable au temps de sérialisation des messages. Cette pour cette raison qu’il est recommandé d’utiliser des types simples (chaînes, GUID ou types numériques).

Exemple de code de grain

Pour illustrer l’utilisation d’un contexte de requête, tenez compte de l’exemple de code de grain suivant :

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

La SayHello méthode enregistre le paramètre entrant greeting , puis récupère l’ID de trace à partir du contexte de requête. Si aucun ID de trace n’est trouvé, les journaux de grain « Aucun ID de trace ».

Exemple de code client

Le client peut définir l’ID de trace dans le contexte de la demande avant d’appeler la SayHello méthode sur le HelloGrain. Le code client suivant montre comment définir un ID de trace dans le contexte de la demande et appeler la SayHello méthode sur :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!

Dans cet exemple, le client définit l’ID de trace sur « example-id-set-by-client » avant d’appeler la SayHello méthode sur le HelloGrain. Le grain récupère l’ID de trace à partir du contexte de la requête et l’enregistre.