我正在编写一个使用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。您可以将租户对象视为只读。 –
我已经用我提出的信号量方法更新了这个问题。 –