C# 多个HTTP请求触发HTTP客户端超时
我有一个应用程序异步发送500个HTTP请求。由于HTTP客户端超时,15秒后处理的所有请求都会失败,即使请求的端点已返回200 OK 代码非常直截了当。在这里,我们获取一块请求(500),并异步执行它们。应该注意的是,下面的函数是在基于消费的计划上运行的Azure函数C# 多个HTTP请求触发HTTP客户端超时,c#,asp.net-core,.net-core,azure-functions,httpclient,C#,Asp.net Core,.net Core,Azure Functions,Httpclient,我有一个应用程序异步发送500个HTTP请求。由于HTTP客户端超时,15秒后处理的所有请求都会失败,即使请求的端点已返回200 OK 代码非常直截了当。在这里,我们获取一块请求(500),并异步执行它们。应该注意的是,下面的函数是在基于消费的计划上运行的Azure函数 public async Task RunBatch(List<Request> requests) { if (requests != null && request
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);
}
}
这里是来自Azure的日志
我希望每个请求都有15秒的超时时间。然而,每当我的服务器处理等待的请求时,我需要它给我一个准确的响应代码。这可能吗
我应该注意:如果Http超时时间更高(1分钟),则所有请求都会成功。尝试增加默认连接限制:
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = <number>;
ServicePointManager.usenaglalgorithm=true;
ServicePointManager.Expect100Continue=true;
ServicePointManager.DefaultConnectionLimit=;
您似乎正在向bing搜索引擎发送请求,对吗?如果我是对的,你还有另一个问题。Bing搜索可能不允许bot请求。因此Bing会阻止请求。请进一步检查。您可以尝试使用一些时间延迟,而不是异步请求。您的应用似乎工作正常。您可以通过向其他服务或API发送请求来验证我的理论。我将检查以下几点:
- 不要每次都使用新的
,而是使用HttpClient
来避免HttpClient构造的开销和端口耗尽HttpClientFactory
- 你确定你没有受到Bing的费率限制吗?尝试将目标锁定在您控制下的远程服务器上
- 考虑使用
或并行库限制请求的并发性信号量lim
我个人认为,试图发出500个并发请求总是容易出错的。您提到您是异步执行的,但实际上,当您启动500个“热门”任务,然后等待它们全部完成时,代码中并没有太多异步 我将使用信号量来控制一次可以发出多少请求。你可能需要玩数字游戏才能找到最佳点 以下代码在LINQPad中运行良好(尽管bing很快注意到奇数请求并开始向页面添加验证码):
async Task Main()
{
var httpClient=新的httpClient();
var URL=Enumerable.Range(1500)。选择(e=>“https://www.bing.com/)。ToList();
//10个并发请求-调整此数字
var信号量=新信号量lim(10,10);
var tasks=url.Select(u=>MakeRequest(u,信号量,httpClient));
var allResponses=wait Task.WhenAll(任务);
//对所有的回答做点什么
}
专用异步任务MakeRequest(字符串url、信号量LIM信号量、HttpClient HttpClient)
{
尝试
{
wait semaphore.WaitAsync();
var request=newhttprequestmessage(HttpMethod.Get,新Uri(url));
var response=wait httpClient.sendaync(请求);
//为进一步节流添加可选延迟:
//等待任务延迟(时间跨度从毫秒(100));
return wait response.Content.ReadAsStringAsync();
}
最后
{
semaphore.Release();
}
}
我用第二张图片更新了我的问题,这张图片更清楚地显示了问题发生的时间。在多次运行中,失败次数不一致。我认为这与连接的数量无关。500个并发请求对于单个客户端来说是一个很大的问题。您需要非常小心地使用线程,以确保您的异步任务能够获得足够的CPU时间来避免触发超时。您可以共享代码吗?L
ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = <number>;
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();
}
}