Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多个HTTP请求触发HTTP客户端超时_C#_Asp.net Core_.net Core_Azure Functions_Httpclient - Fatal编程技术网

C# 多个HTTP请求触发HTTP客户端超时

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

我有一个应用程序异步发送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);
        }
    }
这里是来自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
    ,而是使用
    HttpClientFactory
    来避免HttpClient构造的开销和端口耗尽

  • 你确定你没有受到Bing的费率限制吗?尝试将目标锁定在您控制下的远程服务器上

  • 考虑使用
    信号量lim
    或并行库限制请求的并发性


HttpClient存在一些问题

例如:

  • HttpClient是一次性的:将HttpClient与Using语句一起使用并不是最佳选择,因为即使在处理HttpClient对象时,底层套接字也不会立即释放,并可能导致名为“套接字耗尽”的严重问题。有关此问题的更多信息

  • HttpClient旨在实例化一次,并在应用程序的整个生命周期中重用。为每个请求实例化HttpClient类将耗尽重载下可用的套接字数量。该问题将导致SocketException错误。解决该问题的可能方法是将HttpClient对象创建为单例对象或静态对象

  • 将HttpClient用作单一对象或静态对象时可以使用的HttpClient。在这种情况下,单例或静态HttpClient不尊重DNS更改。有关更多信息:
  • 为了解决上述问题并简化HttpClient实例的管理,.NET Core 2.1引入了一个新的HttpClientFactory

    什么是HttpClientFactory:

  • 为命名和配置逻辑HttpClient对象提供一个中心位置。例如,您可以配置预配置为访问特定微服务的客户端(服务代理)
  • 通过在HttpClient中委派处理程序并实现基于Polly的中间件来利用Polly的弹性策略,从而编纂传出中间件的概念
  • HttpClient已经有了委派处理程序的概念,这些处理程序可以链接在一起用于传出HTTP请求。将HTTP客户机注册到工厂中,可以使用Polly处理程序使用Polly策略进行重试、断路器等操作
  • 管理HttpClientMessageHandler的生存期,以避免在自己管理HttpClient生存期时可能出现的上述问题
  • 有关详细信息,请访问此链接:

    您还可以使用RestSharp库发送任何请求。更多

    参考资源:


  • 我个人认为,试图发出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();
        }
    }