HttpClient перестает повторно использовать соединения после изменения балансировщика нагрузки

У меня есть клиент, который подключается к настройке облачного сервера - экземпляр HAProxy (один из нескольких, определяется балансировщиком нагрузки), который затем перенаправляет запросы на правильный внутренний сервер.

С точки зрения клиента, это всего лишь один постоянный URI, но проблема возникает, когда балансировщик нагрузки переключает экземпляр HAProxy, который обрабатывает запрос. После этого каждый последующий запрос, отправляемый HttpClient, поступает с другого локального порта и обрабатывается внутренним сервером как новое соединение.

Постоянное соединение имеет решающее значение для приложения, поэтому оно серьезно нарушает его работу. Как ни странно, проблема разрешается сама собой после перезапуска клиентского приложения. Это заставляет меня думать, что проблема заключается в клиенте, а не в настройке облака или внутреннем сервере.

Что-то мне здесь не хватает? Я подумал, что это может быть проблема с ServicePointManager, создающим ServicePoint, когда соединение проходит через один экземпляр HAProxy, и поскольку этот объект поддерживается в течение всего срока службы приложения, возможно, есть некоторая проблема с его использованием через второй экземпляр HAProxy. При перезапуске приложения экземпляр ServicePoint теряется и создается заново.


Обновление: сначала я заметил, что объект ServicePoint имеет протокол HTTP 1.1, но как только проблема возникла, он изменился на 1.0. HTTP 1.1 имеет постоянные соединения по умолчанию, тогда как HTTP 1.0 имеет временные соединения по умолчанию.

Если я изменю протокол объекта ServicePoint на 1.0, когда все работает, я получу исключение 502 Bad Gateway (хотя, похоже, оно восстановится и вернется к 1.1 для следующего запроса).

Я предполагаю, что что-то в облачном стеке заставляет протокол измениться на 1.0 после балансировки нагрузки.


person RickySpanish    schedule 05.07.2018    source источник
comment
Как вы используете свой HttpClient? Они завернуты в операторы using или вы избавляетесь от них? Или вы используете одноэлементный экземпляр? Или что-то другое?   -  person mason    schedule 05.07.2018
comment
Экземпляр HttpClient обычно сохраняется, но может быть удален, если сервер закрывает соединение.   -  person RickySpanish    schedule 05.07.2018


Ответы (1)


Похоже, что что-то в облачном стеке устанавливало версию HTTP ответа на 1.0, когда переключатель балансировщика нагрузки вызвал начальную ошибку. Затем клиентский объект ServicePoint для моей конечной точки был обновлен, так что ServicePoint.HttpBehaviour и ServicePoint.ProtocolVersion были 1.0.

HTTP 1.1 имеет постоянные соединения по умолчанию, а 1.0 - нет, поэтому соединения не поддерживаются.

Изменение ServicePoint.HttpBehaviour обратно на 1.1 устраняет проблему, хотя я уверен, что есть правильное исправление конфигурации, которое можно сделать на облачном сервере.

Одна из проблем заключается в том, что HttpBehaviour и ProtocolVersion являются частными свойствами (я менял их с помощью быстрого просмотра отладчика Visual Studio). Они должны быть изменены с помощью отражения, хотя я полагаю, что это не будет изменено в будущих версиях .NET.

person RickySpanish    schedule 05.07.2018