HttpClient и розетка Истощение - уточнение? - PullRequest
1 голос
/ 17 октября 2019

В этой статье говорится, что мы должны использовать статический HttpClient для повторного использования сокетов.

Но в первом комментарии говорится, что существует проблема распознавания изменений DNS, и решение находится в другой статье здесь :

Второйпредложенная статья:

var client = new HttpClient();
client.DefaultRequestHeaders.ConnectionClose = true; 

Который контролирует заголовок KeepAlive. Но страдает от того, что мешает вам воспользоваться преимуществами повторного использования сокета

Другое решение было:

var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute

НО:

Он не сказал, следует лимы используем new Httpclient каждый раз, когда мы хотим сделать запрос, или мы все еще должны использовать статический.

Вопрос:

Скажите, что я хочу использовать это решение:

var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute 
  • Должен ли я по-прежнему использовать static HttpClient подход? или мне new HttpClient каждый раз, когда я хочу позвонить? Или - Должен ли я создавать статические / не статические new HttpClient для каждого scheme://basedns?

Он показал проблему, но в его Заключении не показано полностью правильное окончательное решение.

Обратите внимание - я спрашиваю о .net framework. не .net Core.

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Это очень старая статья, в которой объясняется, почему HttpClient должен использоваться повторно, но не объясняется, как обрабатывать изменения DNS. Это объясняется в Singleton HttpClient? Остерегайтесь этого серьезного поведения и как это исправить . Это все еще касается только одного соединения.

Очевидный ответ - избегать одноэлементных HttpClients, но все же использовать их некоторое время. Кроме того, разные сокеты используются для подключения к разным серверам, что означает, что нам действительно нужно повторно использовать (и перерабатывать) сокеты для каждого сервера. Решение пришло позже в виде HttpClientFactory.

Приятно то, что HttpClientFactory представляет собой пакет .NET Standard 2.0, Microsoft.Extensions.Http , который может использоваться как .NET Core, так и .NET Old, а не только ASP.NETОсновные приложения. Я использую его, например, в консольных приложениях.

Очень хорошее введение - HttpClientFactory в ASP.NET Core 2.1 (PART 1) от Стива Гордона и all егостатьи в этой серии .

Короче говоря, каждый раз, когда нам нужен HttpClient, мы запрашиваем у фабрики экземпляр:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    private readonly IHttpClientFactory _httpClientFactory;

    public ValuesController(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        var client = _httpClientFactory.CreateClient();
        var result = await client.GetStringAsync("http://www.google.com");
        return Ok(result);
    }
}

Делегаты HttpClient работают с SocketClientHandler. Вот что нужно использовать повторно. HttpClientFactory создает экземпляры HttpClient, которые повторно используют обработчики сокетов из пула обработчиков сокетов. Обработчики периодически перезагружаются, чтобы заботиться об изменениях DNS.

Еще лучше, HttpClientFactory можно комбинировать с Polly , чтобы добавить логику повторения в экземпляры HttpClient. Это делает это за сценой, настраивая обработчики.

0 голосов
/ 17 октября 2019

ServicePointManager, на мой взгляд, некорректно и действует только на компьютерах с Windows. Эффективно быть мертвым кодом, если вы перейдете к dotnet core из dotnet framework. Я не буду зависеть от своей реализации.

Я предлагаю создать одноэлементную службу, обслуживающую только один экземпляр HttpClient.

Если вы используете asp.net core, они предоставляют вам реализациюстатического клиента, а также повторно описать проблему в этом документе

...