Подтвердить что ты не робот

Websockets на Tomcat 8 + IIS 8 с ARR 3 не работают

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

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

Этот IIS выполняет балансировку нагрузки с помощью ARR для трех разных сред (все работают с тем же 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_11_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_11_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 до незначительных версий и посмотреть, что-нибудь изменится. Я обновлю здесь, если что-нибудь обнаружу.

Update

Здесь ответ от моего локального сервера (без 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 на OSX не работают.

Обновление 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
4b9b3361

Ответ 1

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

В нашем проекте 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. Наше приложение не отправляет много данных через сокеты, поэтому мы были в порядке, делая этот компромисс.

Ответ 2

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

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