我正在編寫一個使用HttpClient訪問API的類,並且我想限制可以對此類中的某個函數執行的併發調用的數量。竅門是雖然限制是每個租戶,並且多個租戶可能一次使用他們自己的類的實例。通過一些變量來限制HttpClient請求
我的Tenant類只是一個只讀上下文信息的容器。
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
方法,它限制了兩個併發請求每個租戶。我已閱讀使用TPL
或SemaphoreSlim
進行基本調節的建議(例如:Throttling asynchronous tasks),但我不清楚如何補充租戶的進一步複雜性。
感謝您的建議。
UPDATE
我已經嘗試使用一組包含在ConcurrentDictionary
SemaphoreSlim
對象(每個租戶一個)的。這似乎有效,但我不確定這是否理想。新代碼是:
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();
}
}
}
'Tenant'究竟是什麼?它是來自某個圖書館(哪一個?)或您的自定義班級的課程?爲了這個目的修改它是否有意義?另外,一個'Tenant'可以有多個'ApiClient'嗎? – svick
租戶只是一個小的上下文類,它包含租戶的名稱和API客戶端使用的一些連接信息,如用戶名/密碼。我正在使用ASP.NET WebJobs SDK,並且在處理服務總線消息時簡單地注入Tenant。您可以將租戶對象視爲只讀。 –
我已經用我提出的信號量方法更新了這個問題。 –