C# HttpClient问题,如何对不同的URI重复使用?

C# HttpClient问题,如何对不同的URI重复使用?,c#,asp.net-core,asp.net-core-2.0,dotnet-httpclient,C#,Asp.net Core,Asp.net Core 2.0,Dotnet Httpclient,我在Azure应用程序服务上有一个简单的Web应用程序,可以调用两个不同的外部API。昨天,我们的流量出现了一个巨大的预期峰值,整个事情都崩溃了,我现在意识到这是因为我正在创建和处理HttpClient的新实例,如下所示: var url = "https://www.externalapi.com/someendpoint" + "/takethedata.js?" + "[form]email=" + visitor.EmailAddress + "&[for

我在Azure应用程序服务上有一个简单的Web应用程序,可以调用两个不同的外部API。昨天,我们的流量出现了一个巨大的预期峰值,整个事情都崩溃了,我现在意识到这是因为我正在创建和处理HttpClient的新实例,如下所示:

var url = "https://www.externalapi.com/someendpoint" +
    "/takethedata.js?" +
    "[form]email=" + visitor.EmailAddress +
    "&[form]name=" + visitor.FirstName + " " + visitor.LastName +
    "&[form]zip=" + visitor.zip +
    "&[form]location=" + city + ", " + state;

using(var handler = new HttpClientHandler())
{
    handler.ClientCertificateOptions = ClientCertificateOption.Manual;
    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
    handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12 |
        System.Security.Authentication.SslProtocols.Tls11 |
        System.Security.Authentication.SslProtocols.Tls;

    using(var client = new HttpClient(handler))
    {
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage response = await client.GetAsync(url);

    }
}
在另一种方法的同一控制器中,我以同样的方式制作另一个外部API:

string AuthToken = "2678c7b5-3cvt-XXXX-XXXX-XXXXXXXXX";
string BaseUrl = "https://someotherdomain.com/dosomething/" + AuthToken;

var jsonContent = "{ \"param1\": \"" + value1 + "\", \"Timeout\":\"15\", \"Verbose\":\"True\" }";

using(var client = new HttpClient())
{
    client.BaseAddress = new Uri(BaseUrl);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));

    HttpResponseMessage response = await client.PostAsync(BaseUrl,
        new StringContent(jsonContent, Encoding.UTF8, "application/json"));

    if (!response.IsSuccessStatusCode)
    {
        return Json("Email Check Error");
    }
    else
    {
        var responseContent = await response.Content.ReadAsStringAsync();

        return Json(responseContent);
    }
}

我一直在阅读关于HttpClient的文章,并为每个外部API创建一个单例?以及设置不同的URI等问题,我真的很困惑如何继续。如果我只是使用转储,它可能会解决吗?如果我需要创建一个单例,是否有任何地方可以演示我如何做到这一点,并将其应用到我的场景中?谢谢

你到底想做什么?如果我理解正确,您只想在不同的URI上使用相同的HttpClient发出另一个请求,对吗

在这种情况下,您可以使用HttpClient对象调用适当的请求函数,例如GET request:

HttpResponseMessage response = await client.GetAsync(url);

尝试在构造函数中初始化客户机对象,然后继续使用相同的实例,如果您认为每次发送请求时重新实例化它就是问题所在?

您到底想做什么?如果我理解正确,您只想在不同的URI上使用相同的HttpClient发出另一个请求,对吗

在这种情况下,您可以使用HttpClient对象调用适当的请求函数,例如GET request:

HttpResponseMessage response = await client.GetAsync(url);

尝试在构造函数中初始化客户端对象,然后继续使用相同的实例,如果您认为每次发送请求时重新实例化它是问题所在?

建议为每个URL主机创建一个单一实例,即URL的“域”部分。您是对的,管理起来很混乱,所以请看,这是每主机客户机工厂模式。这是一个围绕HttpClient的惊人包装器,可以为您管理缓存复杂性。建议在URL的“域”部分为每个URL主机创建一个单例。您是对的,管理起来很混乱,所以请看,这是每主机客户机工厂模式。这是一个围绕HttpClient的惊人包装器,可以为您管理缓存的复杂性。我知道,创建HttpClient的新实例会使Azure上的应用程序服务应用程序抛出502.3错误,因为在我的情况下,服务器在每秒50多个重负载请求的情况下变得无响应。人们似乎正在做的是创建一个单例并将其注入控制器。但是,对于它如何处理来自原始客户端的每个控制器调用的不同URI,似乎存在一些混淆。。在我的案例中,这就是我在不久前的项目中使用它的方式:在构造函数中创建一个处理程序和客户机对象,并在每次发出请求时调用同一个实例。虽然我的设置证书选项、协议与你的有点不同,所以这可能是问题所在?也可能是BaseAddress属性的问题?是的,如果您使用多个站点,请不要使用基址。您的默认标题是相同的。您只需决定您的证书设置是否兼容。@zl1k4r很好,在我们收到大量请求之前,一切正常。然后使用包装终止服务器。在您的场景中,使用1作为控制器。。演出怎么样?我们收到了7万个请求。现在,我们创建了一个包含两个HttpClient的字典,每个baseURI对应一个。我们将字典注入控制器。似乎正在工作,但不确定扩展问题是否已解决。我知道,创建HttpClient的新实例会使Azure上的应用程序服务应用程序抛出502.3错误,因为在我的情况下,服务器在每秒50多个重负载请求的情况下变得无响应。人们似乎正在做的是创建一个单例并将其注入控制器。但是,对于它如何处理来自原始客户端的每个控制器调用的不同URI,似乎存在一些混淆。。在我的案例中,这就是我在不久前的项目中使用它的方式:在构造函数中创建一个处理程序和客户机对象,并在每次发出请求时调用同一个实例。虽然我的设置证书选项、协议与你的有点不同,所以这可能是问题所在?也可能是BaseAddress属性的问题?是的,如果您使用多个站点,请不要使用基址。您的默认标题是相同的。您只需决定您的证书设置是否兼容。@zl1k4r很好,在我们收到大量请求之前,一切正常。然后使用包装终止服务器。在您的场景中,使用1作为控制器。。演出怎么样?我们收到了7万个请求。现在,我们创建了一个包含两个HttpClient的字典,每个baseURI对应一个。我们将字典注入控制器。似乎正在工作,但不确定是否存在缩放问题 e已解决。