Я отправляю данные телеметрии в конечную точку сборщика данных Application Insights на https://dc.services.visualstudio.com/v2/track
, используя HttpClient
.
Это прекрасно работает при использовании .NET Core 2.0. Однако после обновления до .NET Core 2.1 все запросы не выполняются со статусом HTTP 500 Internal Server Error
и текстом ответа HTML, который выглядит следующим образом:
( Это страница подробных ошибок IIS 8.5 )
В .NET Core 2.1 они изменили , как HttpClientHandler
работает, и добавили переключатель AppContext
, который позволяет нам сохранить старое поведение:
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
Действительно, установка этого переключателя устраняет проблему!
Но я бы хотел не использовать этот переключатель:
- Во-первых, потому что я хотел бы использовать новый материал. Это должно быть лучше: -)
- Во-вторых, потому что этот переключатель изменяет поведение для всех новых
HttpClientHandler
экземпляров. Не только тот, который я использую для публикации данных в конечной точке Application Insights.
Я попытался выяснить причину этого, посмотрев на трафик с помощью Wireshark. Попытка интерпретировать HTTPS-трафик на этом низком уровне мне не по силам. Я нашел что-то подозрительное в рукопожатии TLS.
И SocketsHttpHandler
(который не работает), и устаревший WinHttpHandler
(который работает) используют TLS 1.2. Однако только WinHttpHandler
использует расширение запроса статуса сертификата TLS . Может ли это быть причиной того, что запросы не выполняются?
В любом случае, соединение TLS настроено, запрос отправляется и ответ получен. И, видимо, при обработке запроса на стороне сервера произошла ошибка.
Я бы хотел выяснить, что является причиной этой проблемы. Любая помощь приветствуется!
Как подсказал @mjwills, я изменил свой код, чтобы он использовал HTTP (не SSL) и отправлял сообщения в локальную программу, которая позволяет мне перехватить запрос. (Я не придумал, как сделать это в Wireshark чисто, поэтому в итоге я написал свой собственный маленький инструмент захвата, основанный на TcpListener
):
Захват при использовании нового SocketsHttpHandler
:
POST / HTTP/1.1
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345
A
[...10 bytes of data...]
F4
[...244 bytes of data...]
0
Захват при использовании устаревшего WinHttpHandler
:
POST / HTTP/1.1
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/x-json-stream
Content-Encoding: gzip
Host: localhost:12345
a
[...10 bytes of data...]
f4
[...244 bytes of data...]
0
Вот различия:
WinHttpHandler
хочет сохранить соединение, а SocketsHttpHandler
- нет.
WinHttpHandler
используйте шестнадцатеричный регистр для длин порций, в то время как SocketsHttpHandler
используйте верхний регистр.
Первые 10 байтов содержат заголовок gzip. Оставшиеся 244 байта содержат данные телеметрии JSON в кодировке gzip.