HttpClientを使用してAPIにアクセスするクラスを作成しています。このクラスの特定の関数に対して実行可能な同時呼び出しの数を調整したいと考えています。トリックは、テナントごとに制限があり、複数のテナントがクラスのインスタンスを一度に使用している可能性があります。何らかの変数でHttpClientリクエストを調整する
私のテナントクラスは、読み取り専用コンテキスト情報の単なるコンテナです。ここで
public class Tenant
{
public string Name { get; }
public string ApiKey { get; }
}
はApiClientです:
public class ApiClient
{
private readonly Tenant tenant;
public ApiClient(Tenant tenant)
{
this.tenant = tenant;
}
public async Task<string> DoSomething()
{
var response = await this.SendCoreAsync();
return response.ToString();
}
private Task<XElement> SendCore()
{
using (var httpClient = new HttpClient())
{
var httpRequest = this.BuildHttpRequest();
var httpResponse = await httpClient.SendAsync(httpRequest);
return XElement.Parse(await httpResponse.Content.ReadAsStringAsync());
}
}
}
私が何をしたいのかSendCore
方法を絞るとテナントごとに2つの同時要求に制限されます。私はTPL
またはSemaphoreSlim
を使用して基本的な調整(ここでは:Throttling asynchronous tasksなど)を行う提案を読んだが、テナントのさらなる複雑さをどのように追加するかについては明確ではない。
ありがとうございます。
UPDATE
私はConcurrentDictionary
に含まれるSemaphoreSlim
オブジェクト(テナントごとに1)のセットを使用しようとしました。これはうまくいくようですが、これが理想的かどうかはわかりません。新しいコードは次のとおりです。
public class ApiClient
{
private static readonly ConcurrentDictionary<string, SemaphoreSlim> Semaphores = new ConcurrentDictionary<string, SemaphoreSlim>();
private readonly Tenant tenant;
private readonly SemaphoreSlim semaphore;
public ApiClient(Tenant tenant)
{
this.tenant = tenant;
this.semaphore = Semaphores.GetOrAdd(this.tenant.Name, k => new SemaphoreSlim(2));
}
public async Task<string> DoSomething()
{
var response = await this.SendCoreAsync);
return response.ToString();
}
private Task<XElement> SendCore()
{
await this.semaphore.WaitAsync();
try
{
using (var httpClient = new HttpClient())
{
var httpRequest = this.BuildHttpRequest();
var httpResponse = await httpClient.SendAsync(httpRequest);
return XElement.Parse(await httpResponse.Content.ReadAsStringAsync());
}
}
finally
{
this.semaphore.Release();
}
}
}
「テナント」とは何ですか?それはいくつかのライブラリ(どちらか?)かあなたのカスタムクラスのクラスですか?この目的のためだけに変更するのは理にかなっていますか?また、「テナント」は複数の「ApiClient」を持つことができますか? – svick
テナントはテナントの名前と、username/passwordのようなAPIクライアントによって使用されるいくつかの接続情報を含む小さなコンテキストクラスです。私はASP.NET WebJobs SDKを使用しており、テナントは単にサービスバスメッセージを処理するときに挿入されます。テナントオブジェクトは読み取り専用と考えることができます。 –
私は思いついたセマフォのアプローチで質問を更新しました。 –