Contexto de solicitud
RequestContext es una característica de Orleans que permite que los metadatos de la aplicación, como un identificador de seguimiento, fluyan con las solicitudes. Los metadatos de la aplicación se pueden agregar en el cliente; fluirán con las solicitudes de Orleans al grano receptor. La característica se implementa mediante una clase estática pública, RequestContext
, en el espacio de nombres de Orleans. Esta clase expone dos métodos simples:
void Set(string key, object value)
La API anterior se usa para almacenar un valor en el contexto de la solicitud. El valor puede ser cualquier tipo serializable.
object Get(string key)
La API anterior se usa para recuperar un valor del contexto de solicitud actual.
El almacenamiento de respaldo para RequestContext
es async-local. Cuando el autor de la llamada (ya sea del lado cliente o en Orleans) envía una solicitud, el contenido de RequestContext
de este se incluye con el mensaje de Orleans de la solicitud; cuando el código de grano recibe la solicitud, esos metadatos son accesibles desde el objeto RequestContext
local. Si el código de grano no modifica RequestContext
, cualquier grano que solicite recibirá los mismos metadatos, etc.
Los metadatos de la aplicación también se mantienen cuando se programa un cálculo futuro mediante StartNew o ContinueWith; en ambos casos, la continuación se ejecutará con los mismos metadatos que tenía el código de programación en el momento en que se programó el cálculo (es decir, el sistema realiza una copia de los metadatos actuales y la pasa a la continuación, por lo que los cambios después de la llamada a StartNew
o ContinueWith
no se verán en la continuación).
Importante
Los metadatos de la aplicación no vuelven a fluir con respuestas; es decir, el código que se ejecuta como resultado de una respuesta que se recibe, ya sea dentro de una continuación ContinueWith
o después de una llamada a Task.Wait() o GetValue
, se seguirá ejecutando en el contexto actual que establece la solicitud original.
Por ejemplo, para establecer un identificador de seguimiento en el cliente en un nuevo Guid
, llame a:
RequestContext.Set("TraceId", Guid.NewGuid());
Dentro del código de grano (u otro código que se ejecuta en Orleans en un subproceso del programador), se puede usar el identificador de seguimiento de la solicitud de cliente original al escribir un registro, por ejemplo:
Logger.LogInformation(
"Currently processing external request {TraceId}",
RequestContext.Get("TraceId"));
Aunque se puede enviar cualquier serializable object
como metadatos de la aplicación, merece la pena mencionar que los objetos grandes o complejos pueden agregar una sobrecarga notable al tiempo de serialización de mensajes. Por este motivo, se recomienda el uso de tipos simples (cadenas, GUID o tipos numéricos).
Código de grano de ejemplo
Para ayudar a ilustrar el uso de un contexto de solicitud, tenga en cuenta el código de ejemplo siguiente:
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);
}
El SayHello
método registra el parámetro entrante greeting
y, a continuación, recupera el identificador de seguimiento del contexto de solicitud. Si no se encuentra ningún identificador de seguimiento, los registros de grano "Sin id. de seguimiento".
Código de cliente de ejemplo
El cliente puede establecer el identificador de seguimiento en el contexto de solicitud antes de llamar al SayHello
método en .HelloGrain
El código de cliente siguiente muestra cómo establecer un identificador de seguimiento en el contexto de solicitud y llamar al SayHello
método en 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!
En este ejemplo, el cliente establece el identificador de seguimiento en "example-id-set-by-client" antes de llamar al SayHello
método en .HelloGrain
El grano recupera el identificador de seguimiento del contexto de solicitud y lo registra.