【问题标题】:HttpClient Issues, How do I re-use for different URI's?HttpClient 问题,我如何重新使用不同的 URI?
【发布时间】:2018-03-20 12:45:46
【问题描述】:

我在 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 等问题,我对如何继续感到非常困惑。如果我只是转储“使用”,它可能会解决吗?如果我需要创建一个单例,是否有任何地方可以演示我如何做到这一点并将其应用于我的场景?谢谢!

【问题讨论】:

  • 建议为每个 URL 主机(URL 的“域”部分)创建一个单例。你说得对,管理起来很混乱,所以查看the Flurl library,它是每个主机客户端工厂模式。它是一个惊人的 HttpClient 包装器,可以为您管理缓存的复杂性。

标签: c# asp.net-core asp.net-core-2.0 dotnet-httpclient


【解决方案1】:

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

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

HttpResponseMessage response = await client.GetAsync(url);

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

【讨论】:

  • 我知道创建新的 HttpClient 实例会使我在 Azure 上的应用服务应用程序抛出 502.3 错误,因为服务器在重负载下变得无响应(在我的情况下每秒 50 多个请求)。人们似乎在做的是创建一个单例并将其注入控制器。 stackoverflow.com/questions/22560971/…pastebin.com/9ypJcw9X 但似乎有些混淆它如何与来自原始客户端的每个控制器调用的不同 URI 一起工作.. 就我而言
  • 这就是我不久前在自己的项目中使用它的方式:在构造函数中创建处理程序和客户端对象,并在每次发出请求时调用相同的实例。虽然我的设置(证书选项、协议)与您的有点不同,但这可能是问题所在?
  • BaseAddress 属性也可能有问题? stackoverflow.com/questions/23438416/…
  • 是的,如果您使用多个站点,请不要使用基地址。您的默认标题是相同的。您只需要确定您的证书设置是否兼容。
  • @zl1k4r 一切正常,直到我们收到大量请求。然后包装使用杀死的服务器。在您的场景中,控制器使用 1 .. 性能如何?我们收到了 7 万个请求。现在我们创建了一个包含两个 httpclients 的字典,每个 baseURI 一个。我们将字典注入到控制器中。似乎正在工作,但不确定缩放问题是否已解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多