Как я должен использовать HttpClient в ASP.NET Core 2.0 API

Я работаю над API-интерфейсом ASP.NET Core 2.0, и мой API должен вызывать другой, сторонний API REST для загрузки и получения файлов, а также для получения списков файлов и информации о состоянии. Я буду размещать API в Azure и планирую развертывать Blue-Green между моими промежуточными и производственными слотами.

Похоже, что общий консенсус для наилучшей практики состоит в том, чтобы настроить экземпляр SingleControl HTTPClient через регистрацию DI в методе Startup.cs ->ConfigureSerrvices, чтобы повысить производительность и избежать ошибок сокетов, которые могут возникнуть, если я заново создаю утилиту соединение HTTPClient с каждым использованием через оператор Using. Это отмечено в следующих ссылках;

https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.110).aspx

http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/

Но если я это сделаю, то могу столкнуться с проблемой, когда экземпляр Singleton не увидит никаких изменений DNS при выполнении развертывания Blue-Green в Azure. Это отмечено в следующих ссылках;

http://byterot.blogspot.co.uk/2016/07/singleton-httpclient-dns.html

https://github.com/dotnet/corefx/issues/11224

http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/

Итак, общий консенсус теперь заключается в том, чтобы использовать статический экземпляр HTTPClient, но управлять значением ConnectionLeaseTimeout класса ServicePoint, чтобы установить для него более короткое значение, которое принудительно закроет соединение, чтобы получить обновление DNS. В этом посте даже рассказывается о хорошем компоненте RestClient в пакете nuget (Easy.Common от Nima), который правильно обращается к ConnectionLeaseTimeout, а также кешированным значениям DNS.

Однако, похоже, что ASP.NET Core 2.0 не полностью реализует ServicePoint, и поэтому этот подход в настоящее время не поддерживается в ASP.Net Core 2.0.

Может ли кто-нибудь посоветовать мне правильный подход к использованию HttpClient в моем ASP.NET Core 2.0 API, работающем в Azure? Я хочу иметь возможность делать сине-зеленые развертывания. Итак, я должен просто прибегнуть к выражению Using и обновлять клиент при каждом использовании и просто страдать от снижения производительности?

Просто кажется, что должно быть надежное и эффективное решение этой общей проблемы.

3 ответа

Решение

Проблема некоторых статей, на которые вы ссылаетесь, состоит в том, что они привели к широко распространенному убеждению, что ConnectionLeaseTimeout выполняет какую-то черную магию в слое сокетов, и если вы находитесь на платформе, которая не поддерживает ее, вы облажались. Эти статьи оказывают плохую услугу, не затрагивая то, что на самом деле делает этот параметр, который отправляет Connection: Close заголовок к серверу, вызываемому через равные промежутки времени. Вот и все. Я подтвердил это из источника, и его очень легко воспроизвести. Фактически я сделал это сам в своей библиотеке Flurl, подробности реализации здесь и здесь.

Тем не менее, я лично считаю, что проблема DNS немного преувеличена. Обратите внимание, например, что соединения автоматически закрываются после простоя в течение определенного периода времени (по умолчанию 100 секунд). Преимущества использования HttpClient как синглтон намного перевешивает риски.

Мой совет - использовать экземпляр для каждой вызываемой сторонней службы. Мысль здесь заключается в том, что вы получаете максимальное повторное использование, в то же время используя DefaultRequestHeaders, которые, как правило, специфичны для одной услуги. Если вы звоните только по одной услуге, это всего лишь синглтон. (И наоборот, если вы звоните 1000 разным сервисам, вы не можете избежать 1000 открытых сокетов, как бы вы их ни разрезали.) Если вы не ожидаете, что соединение когда-либо будет долго бездействовать, и хотите защититься от возможных коммутаторов DNS со сторонним сервисом, отправьте Connection: close заголовок, или просто распоряжаться и воссоздавать HttpClientчерез равные промежутки времени. И обратите внимание, что это компромисс, а не идеальное решение, которое должно помочь смягчить проблему.

Документация сбивает с толку и соответствующие статьи утверждают, что у вас должен быть только один HttpClient Например, некоторые вводят в заблуждение (или вводят в заблуждение, в зависимости от перспективы).

Совет состоит в том, чтобы иметь только один экземпляр на жизненный цикл приложения, но на самом деле, когда вы говорите о веб-приложении, это должно быть ограничено запросом жизненного цикла. Когда документация предупреждает о обновлении HttpClient для каждого запроса речь идет о каждом запросе, сделанном через HttpClientне каждый запрос, обслуживаемый вашим веб-приложением, который просто использует HttpClient,

Длинный и короткий, да, вы должны избегать using с HttpClient, но иметь экземпляр в области запроса - это нормально. Другими словами, это не обязательно должен быть синглтон.

Начиная с версии 2.1, хорошим вариантом является использование IHttpClientFactory,

Документы Microsoft | Объявление в блоге

Другие вопросы по тегам