Как увеличить максимальное кол-во tcp-соединений используя webclient?

Рейтинг: 1Ответов: 1Опубликовано: 28.06.2023

Мне нужно отправлять большое кол-во http-запросов параллельно (десятки тысяч в минуту) Пытаюсь реализовать это с помощью асинхронных методов webclient. Я установил значение "System.Net.ServicePointManager.DefaultConnectionLimit=10000" Все работает довольно быстро, но во время выполнения запросов, netstat показывает, что открыто всего ~400 tcp соединений, соответственно, что-то ограничивает максимальное число соединений? Вопрос, можно ли как-то увеличить максимальное количество одновременных соединений, используя webclient, или возможно мне стоит выбрать другую библиотеку для моей задачи?

Ответы

▲ 3Принят

Для начала используйте .NET 6 и новее, работать будет еще быстрее.

ServicePointManager работает только для устаревшего HttpWebRequest/HttpWebRequestHandler который устарел вместе со .NET Framework 4.x, а в .NET Core и выше WebClient под капотом использует HttpClient, а тот в свою очередь - SocketsHttpHandler.

  1. Для новой разработки использовать сразу асинхронный HttpClient напрямую
  2. Его соединениями тонко можно управлять передав ему в конструктор экземпляр настроенного SocketsHttpHandler.

При обращении к одному и тому же хосту лучше использовать HTTP/2 и одно единственное соединение. За счет особенностей протокола через одно соединение мультиплексируется большое число запросов. Для HTTP/1.1 можно регулировать количество одновременных подключений к одному и тому же серверу через SocketsHttpHandler.MaxConnectionsPerServer. Количество одновременных подключений к разным хостам не ограничено.

HttpClientHandler создаст правильный handler для текущей платформы. В новых версиях .NET это будет SocketsHttpHandler, можно использовать конструктор SocketsHttpHandler явно, если требуется.

private static readonly HttpClient client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All })
{
    DefaultRequestVersion = HttpVersion.Version20
};

Используйте один и тот же client для всех запросов. Этого хватает для большинства приложений. Плюс ко всему если запросы идут к одному и тому же серверу, то открытое соединение будет переиспользоваться. А для HTTP/2 оно будет вообще одно, и так и должно быть, это никак не режет производительность, а наоборот повышает.

Для более сложных и тонко настраиваемых случаев с высоконагруженной работой рекомендуется использовать IHttpClientFactory.