Веб-сокеты на Tomcat 8 + IIS 8 с ARR 3 не работают

Я поискал в Интернете, пытаясь найти кого-нибудь, кто мог бы столкнуться с этой проблемой, но пришел с пустыми руками. Итак, вот и:

У нас есть веб-приложение на Java (на основе Spring MVC 4). Он стоит за Microsoft IIS, выступая в качестве балансировщика нагрузки / обратного прокси-сервера с использованием маршрутизации запросов приложений (ARR) v3.

Этот IIS выполняет балансировку нагрузки с ARR для 3 различных сред (все они работают с одним и тем же кодом Java): dev.example.com, demo.example.com и qa.example.com.

Приложение отправляет уведомления в браузеры пользователей с помощью WebSockets через SockJS и Stompjs, и все это хорошо работало, пока серверы приложений были на Tomcat 7. После обновления среды qa.example.com до Tomcat 8 соединения WebSocket перестали работать - оно возвращается к XHR POST запросы.

Хочу подчеркнуть, что в IIS не было внесено никаких изменений, только сервер приложений qa.

Вот пример запроса / ответа из dev среды (рабочая):

Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Cookie: <cookies snipped>
Host: dev.example.com
Origin: https://dev.example.com
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: E7aIek0X6qcO9PAl1n6w4Q==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:18:30 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: P+fEH8pvxcu3sEoO5fDizjSbwJc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block
0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36

Ответ

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:19:35 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: dKYK05s4eP87iA20aSo/3ntOrPU=
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block

Вот пример запроса / ответа из среды qa (неработающей):

Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cache-Control: no-cache
Connection: Upgrade
Cookie: <cookies snipped>
Host: qa.example.com
Origin: https://qa.example.com
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: jTOIAT0+o35+Qi0ZWh2gyQ==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:18:30 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: P+fEH8pvxcu3sEoO5fDizjSbwJc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block
0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36

Ответ:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: Upgrade
Date: Thu, 22 Oct 2015 02:18:30 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: P+fEH8pvxcu3sEoO5fDizjSbwJc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Microsoft-IIS/8.0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: Websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Powered-By: ARR/3.0
X-XSS-Protection: 1; mode=block

Единственное очевидное отличие состоит в том, что ответ qa включает заголовок Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15, а ответ dev - нет.

Я включил «Отслеживание неудачных запросов» в IIS для отладки ответа 101 и вижу, что некоторые заголовки перезаписываются IIS, а именно заголовок Sec-WebSocket-Accept.

IIS также показывает, что этот запрос создает 502.5 ошибку. Я поискал это и нашел следующее: https://support.microsoft.com/en-us/kb/943891, в котором говорится, что 502.5 это «сбой WebSocket (ARR)», и это все, что в нем говорится. Как ни странно, Chrome Dev Tools показывает, что он отвечает 101, как и предполагалось ...

Я пробовал все это с локальным сервером приложений (Tomcat 8 без IIS), и веб-сокеты работали нормально. Tomcat 7 + IIS + ARR + WebSockets работает нормально. Tomcat 8 + IIS + ARR + WebSockets - нет.

Моя точная версия Tomcat 8 - 8.0.28, но я получил те же результаты на Tomcat 8.0.26.

Мой следующий шаг - продолжать понижать Tomcat 8 до младших версий и смотреть, не изменится ли что-нибудь. Я обновлю здесь, если что-нибудь обнаружу.

Обновлять

Вот ответ моего локального сервера (без IIS):

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: upgrade
Date: Thu, 22 Oct 2015 13:59:23 GMT
Expires: 0
Pragma: no-cache
Sec-WebSocket-Accept: 718HnPxHN8crYYzNGFjQf7w8O+Y=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Server: Apache-Coyote/1.1
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
Upgrade: websocket
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

Он очень похож на сломанный запрос qa, но отлично работает. Так что я думаю, что эта вещь Sec-WebSocket-Extensions была отвлекающим маневром. Также Upgrade: websocket и Connection: upgrade - это строчные буквы на моем локальном сервере, тогда как это Websocket и Upgrade, когда вы помещаете IIS впереди.

Sec-WebSocket-Extensions также имеет конечный пробел в qa после permessage-deflate;, но в локальном нет.

Обновление 2

Все это отлично работает в qa среде в Microsoft Edge (Windows 10). Я не пробовал Internet Explorer 11, но должен предположить, что он, вероятно, также работает. Firefox и Chrome в OS X не работают.

Обновление 3

Запрос от Tomcat до его изменения IIS / ARR:

HTTP/1.1 101 Switching Protocols
Server: Apache-Coyote/1.1
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: luP49lroNK9qTdaNNnSCLXnxAWc=
Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15
Date: Tue, 27 Oct 2015 21:10:48 GMT

person Will Warren    schedule 22.10.2015    source источник
comment
Можете ли вы отключить сжатие в веб-сокетах для Tomcat? Sec-WebSocket-Extensions: permessage-deflate; предполагает, что он сжимается, по моему опыту, IIS не проксировал сжатые веб-узлы.   -  person timmah.faase    schedule 28.01.2016
comment
@ timmah.faase Я попробую и доложу   -  person Will Warren    schedule 01.02.2016
comment
Итак, я попытался добавить эту опцию в свою конфигурацию Tomcat: -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true, которая должна была выполнить трюк в соответствии с документами: If true, disable all built-in extensions provided by the server, such as message compression., но, похоже, она вообще не изменила заголовки ответов   -  person Will Warren    schedule 06.02.2016


Ответы (4)


Я нашел решение, хотя оно не так удовлетворительно, как мне хотелось бы.

В pom.xml нашего проекта у нас было spring-core:4.2.5, но spring-websocket и spring-messaging были 4.1.6. Несоответствие версий явно вызывало некоторые проблемы.

Установка -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true в параметрах запуска Tomcat при несовпадении версий ни на что не повлияла. Установка этой опции JVM, когда версии были одинаковыми, работала должным образом.

Ответ 101 теперь не содержит permessage-deflate, и веб-сокеты могут без проблем подключаться через IIS. Наше приложение не отправляет много данных через сокеты, поэтому мы согласились пойти на этот компромисс.

person Will Warren    schedule 08.03.2016
comment
Все библиотеки Spring, которые я использую, имеют версию 4.3.6, и я тоже столкнулся с этой проблемой. Я могу подтвердить, что отключение расширений websocket работает, но я должен согласиться, что это не очень удовлетворительное решение, поскольку сжатие выходит за рамки. Было бы приветствоваться любое другое решение. - person Ron; 09.05.2017

У меня такая же проблема. Обходной путь - переопределить заголовок обработки сжатия Websockets от клиента с помощью ARR. IE не использует принудительное сжатие и не пытается использовать сжатие Websocket, но Chrome и Firefox выдадут запрос с заголовком «Sec-WebSocket-Extensions: permessage-deflate».

Поскольку я не мог повлиять на свой внутренний сервер NodeJS, мне пришлось решить эту проблему в ARR.

Взгляните на эту статью.

https://community.home-assistant.io/t/solved-access-via-iis-reverse-proxy-died-after-upgrade-to-0-58/34408

У меня это сработало.

После модификаций заголовок был замещен пустым значением в моем входящем правиле перезаписи, и ARR не имел проблем с обработкой запросов и ответов Websocket, потому что они не были сжаты этим, и ARR мог обрабатывать их с активированным модулем Websockets в IIS.

person Robert Grumann    schedule 03.08.2018

Та же проблема на Tomcat7 и IIS8 с использованием ARR3. Мы не используем библиотеки Spring.

Никакие кадры не отправляются после установления соединения с веб-сокетом, если включены расширения веб-сокета. Но если мы отключили веб-расширения, то все работает отлично.

person David Pérez Serrada    schedule 08.07.2016
comment
Интересно, как мы могли бы отправить отчет об ошибке для этого - это точно похоже на ошибку! Интересно, есть ли Microsoft Connect для IIS ... - person Will Warren; 10.07.2016

У нас была такая же проблема с прокси-сервером приложения Azure AD перед Tomcat. Нам пришлось отключить Sec-WebSocket-Extensions в Tomcat.

person R3tty    schedule 02.10.2018