我有一个应用程序异步发送 500 个 HTTP 请求。由于 HTTP 客户端超时,15 秒后处理的所有请求都会失败,即使请求的端点已返回 200 OK,也是如此。
代码非常简单。这里我们获取一大块请求(500),并异步执行它们。应该注意的是,下面的函数是在基于消耗的计划上运行的 Azure 函数。
public async Task RunBatch(List<Request> requests)
{
if (requests != null && requests .Count > 0)
{
var tasks = new Task[requests.Count];
var i = 0;
foreach (var request in requests)
{
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(request.Url));
request.Content = new StringContent(request.BodyString, Encoding.UTF8, "application/json");
tasks[i] = _httpClient.SendAsync(request);
i++;
}
await Task.WhenAll(tasks);
}
}
我的构造函数中存在以下代码
_httpClient = new HttpClient();
_httpClient.Timeout = new TimeSpan(0, 0, 15); // 15 seconds
以下是来自 Azure 的日志。
我希望每个请求的超时时间为 15 秒。但是,每当我的服务器开始处理等待的请求时,我都需要它给我一个准确的响应代码。这可能吗?
我应该注意:使用较高的 Http 超时(1 分钟),所有请求都会成功。
最佳答案
就我个人而言,我认为尝试发出 500 个并发请求总是容易出错。您提到您正在异步执行此操作,但实际上,当您启动 500 个“热门”任务然后等待它们全部完成时,您的代码中并没有太多异步。
我会使用信号量来控制一次可以发出多少个请求。您可能需要玩弄数字才能找到最佳位置。
以下代码在 LINQPad 中运行良好(尽管 bing 很快注意到奇数个请求并开始向页面添加验证码):
// using System.Threading;
async Task Main()
{
var httpClient = new HttpClient();
var urls = Enumerable.Range(1, 500).Select(e => "https://www.bing.com/").ToList();
// 10 concurrent requests - tweak this number
var semaphore = new SemaphoreSlim(10, 10);
var tasks = urls.Select(u => MakeRequest(u, semaphore, httpClient));
var allResponses = await Task.WhenAll(tasks);
// Do something with allResponses
}
private async Task<string> MakeRequest(string url, SemaphoreSlim semaphore, HttpClient httpClient)
{
try
{
await semaphore.WaitAsync();
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(url));
var response = await httpClient.SendAsync(request);
// Add an optional delay for further throttling:
//await Task.Delay(TimeSpan.FromMilliseconds(100));
return await response.Content.ReadAsStringAsync();
}
finally
{
semaphore.Release();
}
}
关于c# - 多个HTTP请求触发HTTP Client超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60013771/