Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1135. #ЗаметкиНаПолях Избегаем Проблем с DNS в HttpClient HttpClient позволяет отправлять HTTP-запросы. Подразумевается, что он создаётся однократно и повторно используется на протяжении всего жизненного цикла приложения. HttpClient имеет пул для повторного использования соединений. Если вы отправите несколько запросов на один и тот же хост, они будут повторно использовать одно и то же соединение. Таким образом, приложение экономит доступные ему сокеты. Кроме того, это повышает производительность приложения, избегая рукопожатий TCP и TLS для каждого запроса к одному и тому же хосту. Сохранение соединений открытыми - хорошо с точки зрения производительности, но вы должны быть осторожны, чтобы не хранить устаревшие соединения. Если срок жизни DNS истёк, хост может изменить свой IP-адрес. В этом случае открытые соединения должны быть закрыты. HttpClient не делает этого автоматически, поскольку ему ничего не известно о сроке жизни DNS. Когда происходит изменение DNS? - При сине-зелёном развёртывании (в Azure, когда вы выполняете развёртывание в промежуточном слоте, а затем переключаете рабочий/промежуточный слоты). - При изменении настроек в диспетчере трафика Azure. - В случае отказа основного сервера и перехода на бекап и т.п. Чтобы исправить эту проблему, вы можете указать время ожидания для автоматического закрытия соединения. SocketsHttpHandler используется для настройки поведения HttpClient и его пула соединений. Необходимо настроить 2 свойства: - PooledConnectionIdleTimeout, - PooledConnectionLifetime. Эти свойства заставляют HttpClient закрыть соединение через определённое время. Таким образом, следующий запрос к тому же хосту должен будет открыть новое соединение и использовать новый DNS или другие изменения в сети. По умолчанию простаивающие соединения закрываются через 1 минуту. Однако активные соединения никогда не закрываются. Вы должны явно установить для PooledConnectionLifetime желаемое значение.
using System.Threading;
using System.Net.Http;

using var handler = new SocketsHttpHandler()
{
  // Максимальное время простоя соединения в пуле. Если в течение этого времени нет запросов, соединение разрывается. По умолчанию: 1 минута
  PooledConnectionIdleTimeout = 
   TimeSpan.FromMinutes(1),

  // Максимальное время жизни соединения в пуле, независимо от активности. Периодически соединение пересоздаётся для обновления DNS или других сетевых изменений. По умолчанию: никогда.
  PooledConnectionLifetime = 
   TimeSpan.FromMinutes(1)
};

using var client = new HttpClient(handler);

var timer = new PeriodicTimer(
  TimeSpan.FromSeconds(10));

while (await timer.WaitForNextTickAsync())
{
  _ = await client
    .GetStringAsync("https://www.google.com");
}

Замечание: Другой способ избежать проблем с изменённым DNS – использовать IHttpClientFactory:
services
  .AddHttpClient<IMyService, MyService>()
  .SetHandlerLifetime(TimeSpan.FromMinutes(1));

Источник: www.meziantou.net/avoid-d…tnet.htm