要求內容
RequestContext 是一項 Orleans 功能,可讓應用程式中繼資料 (例如追蹤識別碼) 透過要求傳送。 應用程式中繼資料可新增到用戶端上;它會透過 Orleans 要求傳送至接收端粒紋。 此功能是由 Orleans 命名空間中的公用靜態類別 RequestContext
所實作。 此類別會公開兩個簡單的方法:
void Set(string key, object value)
上述 API 可用來將值儲存在要求內容中。 此值可以是任何可序列化型別。
object Get(string key)
上述 API 可用來從目前的要求內容中擷取值。
RequestContext
的支援儲存體為非同步本機。 當呼叫端 (無論是用戶端還是 Orleans 內部) 傳送要求時,呼叫端 RequestContext
的內容都會連同 Orleans 訊息包含在要求中;當粒紋程式碼收到要求時,可從本機 RequestContext
存取該中繼資料。 如果粒紋程式碼未修改 RequestContext
,則受到其要求的任何粒紋都會接收到相同的中繼資料,依此類推。
當您使用 StartNew 或 ContinueWith 排程未來的計算時也會保有應用程式中繼資料;在這兩種情況下,接續都會使用與排程程式碼在排程接續時具備的相同中繼資料來執行 (也就是說,系統會建立目前中繼資料的複本,並將其傳至接續,因此接續將不會看到在呼叫 StartNew
或 ContinueWith
之後產生的變更)。
重要
應用程式中繼資料不會透過回應傳回;也就是說,因收到回應而執行的程式碼 (在 ContinueWith
接續內或呼叫 Task.Wait() 或 GetValue
之後),仍會在原始要求所設定的目前內容中執行。
例如,若要將用戶端中的追蹤識別碼設定為新的 Guid
,您可以呼叫:
RequestContext.Set("TraceId", Guid.NewGuid());
在粒紋程式碼 (或在排程器執行緒上的 Orleans 內執行的其他程式碼) 內,可以使用原始用戶端要求的追蹤識別碼 (例如,在撰寫記錄時):
Logger.LogInformation(
"Currently processing external request {TraceId}",
RequestContext.Get("TraceId"));
雖然任何可 object
串行化的物件都可以當做應用程式元數據傳送,但值得一提的是,大型或複雜的物件可能會為訊息串行化時間增加明顯的額外負荷。 因此,建議使用簡單型別 (字串、GUID 或數值型別)。
範例粒紋程序代碼
若要協助說明使用要求內容,請考慮下列範例粒紋程序代碼:
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);
}
方法 SayHello
會記錄傳入 greeting
參數,然後從要求內容擷取追蹤標識碼。 如果找不到追蹤標識碼,則粒紋會記錄「沒有追蹤標識碼」。
範例客戶端程序代碼
用戶端可以在要求內容中設定追蹤標識碼,然後再呼叫 SayHello
上的 HelloGrain
方法。 下列用戶端程式代碼示範如何在要求內容中設定追蹤識別碼,並在上HelloGrain
呼叫 SayHello
方法:
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!
在此範例中,用戶端會在 上HelloGrain
呼叫 SayHello
方法之前,先將追蹤標識符設定為 “example-id-set-by-client”。 粒紋會從要求內容擷取追蹤標識碼,並加以記錄。