带有 ARR 3 的 Tomcat 8 + IIS 8 上的 Websockets 无法正常工作更新更新 2更新 3

2022-09-03 07:37:23

我在互联网上搜索了一下,试图找到任何可能遇到这个问题但空手而归的人。所以这里是:

我们有一个java Web应用程序(基于Spring MVC 4)。它位于Microsoft IIS后面,使用应用程序请求路由(ARR)v3充当负载平衡器/反向代理。

此 IIS 使用 ARR 对 3 个不同的环境(所有环境都运行相同的 Java 代码)执行负载平衡:和 。dev.example.comdemo.example.comqa.example.com

该应用程序通过SockJS和stompjs向使用WebSockets的用户浏览器提供通知,当应用程序服务器在Tomcat 7上时,这一切都运行良好。将环境升级到 Tomcat 8 后,WebSocket 连接停止工作 - 它回退到 XHR POST 请求。qa.example.com

我想强调的是,没有对 IIS 进行任何更改,只是对应用程序服务器进行了更改。qa

下面是来自开发环境的示例请求/响应(工作):

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

唯一明显的区别是响应包含标头,而响应不包含标头。qaSec-WebSocket-Extensions: permessage-deflate;client_max_window_bits=15dev

我在IIS上打开了“失败请求跟踪”来调试响应,我可以看到有一些标头被IIS覆盖 - 即标头。101Sec-WebSocket-Accept

IIS 还显示该请求正在创建错误。我查了一下,发现这个:https://support.microsoft.com/en-us/kb/943891 上面写着“WebSocket failure (ARR)”,这就是它所说的一切。奇怪的是,Chrome Dev Tools显示它以101响应,就像它应该的那样......502.5502.5

我用本地应用程序服务器(没有IIS的Tomcat 8)尝试了这一切,websockets工作得很好。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

它看起来很像损坏的请求,但它工作得很好。所以我想那东西是一条红鲱鱼。此外,在我的本地服务器上也是小写的,而当您将IIS放在前面时,它是小写的。qaSec-WebSocket-ExtensionsUpgrade: websocketConnection: upgradeWebsocketUpgrade

Sec-WebSocket-Extensions在后面也有一个尾随空格,但本地没有。qapermessage-deflate;

更新 2

在Microsoft Edge(Windows 10)中的环境中,这一切都很好,我还没有尝试过Internet Explorer 11,但我必须假设它可能也可以工作。OSX上的Firefox和Chrome不起作用。qa

更新 3

在被 IIS/ARR 修改之前,Tomcat 的请求:

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

答案 1

我已经发现了解决方案,尽管它并不像我希望的那样令人满意。

在我们的项目中,我们有但是并且是.版本不匹配显然导致了一些问题。pom.xmlspring-core:4.2.5spring-websocketspring-messaging4.1.6

当版本不匹配时,在Tomcat启动选项中进行设置没有任何影响。当版本相同时设置该JVM选项与预期一样有效。-Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true

响应现在不包含,并且 websocket 能够通过 IIS 毫无问题地进行连接。我们的应用程序不会通过套接字发送大量数据,因此我们可以进行这种权衡。101permessage-deflate


答案 2

我遇到了同样的问题。解决方法是使用ARR覆盖来自客户端的Websockets压缩处理标头。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可以使用IIS中激活的Websockets模块来处理它们。


推荐