Tomcat 8 + IIS 8 和 ARR 3 上的 Websockets 不工作
Websockets on Tomcat 8 + IIS 8 with ARR 3 are not working
我在互联网上搜索过,试图找到可能遇到此问题但一无所获的人。所以这里是:
我们有一个 java 网络应用程序(基于 Spring MVC 4)。它位于 Microsoft IIS 后面,使用应用程序请求路由 (ARR) v3 作为负载平衡器/反向代理。
此 IIS 正在使用 ARR 为 3 个不同的环境执行负载平衡(所有 运行 相同 Java 代码):dev.example.com
, demo.example.com
和 qa.example.com
.
该应用程序通过 SockJS 和 stompjs 使用 WebSockets 向用户的浏览器提供通知,当应用程序服务器在 Tomcat 上时,这一切都运行良好 7. 将 qa.example.com
环境升级到 Tomcat 8,WebSocket 连接停止工作 - 它退回到 XHR POST 请求。
我想强调的是,没有对 IIS 进行任何更改,只是 qa
应用程序服务器。
这是来自 dev
环境(工作)的示例 request/response:
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
环境(损坏)的示例 request/response:
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
header 而 dev
响应不包含。
我在 IIS 上打开 "Failed Request Tracing" 来调试 101
响应,我可以看到有一些 headers 被 IIS 覆盖 - Sec-WebSocket-Accept
header 即.
IIS 还显示该请求正在创建 502.5
错误。我查了一下,发现这个:https://support.microsoft.com/en-us/kb/943891 说 502.5
是 "WebSocket failure (ARR)",这就是它所说的全部内容。奇怪的是,Chrome Dev Tools 显示它响应 101 就像它应该的那样...
我用本地应用程序服务器(Tomcat 8,没有 IIS)尝试了这一切,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
它看起来很像损坏的 qa
请求,但效果很好。所以我猜 Sec-WebSocket-Extensions
是个转移注意力的东西。另外 Upgrade: websocket
和 Connection: upgrade
在我的本地服务器上是小写的,而当你把 IIS 放在前面时它是 Websocket
和 Upgrade
。
Sec-WebSocket-Extensions
在 permessage-deflate;
之后的 qa
中也有尾随 space 但本地没有。
更新 2
在 Microsoft Edge (Windows 10) 的 qa
环境中一切正常 我还没有尝试过 Internet Explorer 11,但我不得不假设它可能也有效。 OSX 上的 Firefox 和 Chrome 不工作。
更新 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
我已经找到了解决方案,尽管它并不像我希望的那样令人满意。
在我们项目的 pom.xml
中,我们有 spring-core:4.2.5
,但 spring-websocket
和 spring-messaging
是 4.1.6
。版本不匹配显然导致了一些问题。
当版本 不匹配 时,在 Tomcat 启动选项中设置 -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true
无效。当版本相同时设置该 JVM 选项按预期工作。
101
响应现在不包含 permessage-deflate
并且 websockets 能够通过 IIS 毫无问题地连接。我们的应用程序不会通过套接字发送大量数据,因此我们可以做出这种权衡。
在使用ARR3 的Tomcat7 和IIS8 上出现同样的问题。我们没有使用 Spring 个库。
如果启用了 websocket-extensiones,则在建立 websocket 连接后不会发送任何帧。但是如果我们禁用 websocket-extensions 那么一切都会完美。
我遇到了同样的问题。
解决方法是使用 ARR 从客户端覆盖 Websockets 压缩处理 header。
IE 不会强制或尝试 Websocket 压缩,但 Chrome 和 Firefox 将发出带有 Header "Sec-WebSocket-Extensions: permessage-deflate".
的请求
由于我无法影响我的 NodeJS 后端服务器,我不得不在 ARR 中解决这个问题。
看看这篇文章。
它对我有用。
修改后,Header 在我的入站重写规则中被空白值覆盖,ARR 处理 Websocket 请求和响应没有问题,因为它们没有被压缩,ARR 可以处理它们在 IIS 中激活 Websockets 模块。
我们在 Tomcat 前面的 Azure AD 应用程序代理遇到了同样的问题。我们必须在 Tomcat.
中禁用 Sec-WebSocket-Extensions
我在互联网上搜索过,试图找到可能遇到此问题但一无所获的人。所以这里是:
我们有一个 java 网络应用程序(基于 Spring MVC 4)。它位于 Microsoft IIS 后面,使用应用程序请求路由 (ARR) v3 作为负载平衡器/反向代理。
此 IIS 正在使用 ARR 为 3 个不同的环境执行负载平衡(所有 运行 相同 Java 代码):dev.example.com
, demo.example.com
和 qa.example.com
.
该应用程序通过 SockJS 和 stompjs 使用 WebSockets 向用户的浏览器提供通知,当应用程序服务器在 Tomcat 上时,这一切都运行良好 7. 将 qa.example.com
环境升级到 Tomcat 8,WebSocket 连接停止工作 - 它退回到 XHR POST 请求。
我想强调的是,没有对 IIS 进行任何更改,只是 qa
应用程序服务器。
这是来自 dev
环境(工作)的示例 request/response:
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
环境(损坏)的示例 request/response:
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
header 而 dev
响应不包含。
我在 IIS 上打开 "Failed Request Tracing" 来调试 101
响应,我可以看到有一些 headers 被 IIS 覆盖 - Sec-WebSocket-Accept
header 即.
IIS 还显示该请求正在创建 502.5
错误。我查了一下,发现这个:https://support.microsoft.com/en-us/kb/943891 说 502.5
是 "WebSocket failure (ARR)",这就是它所说的全部内容。奇怪的是,Chrome Dev Tools 显示它响应 101 就像它应该的那样...
我用本地应用程序服务器(Tomcat 8,没有 IIS)尝试了这一切,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
它看起来很像损坏的 qa
请求,但效果很好。所以我猜 Sec-WebSocket-Extensions
是个转移注意力的东西。另外 Upgrade: websocket
和 Connection: upgrade
在我的本地服务器上是小写的,而当你把 IIS 放在前面时它是 Websocket
和 Upgrade
。
Sec-WebSocket-Extensions
在 permessage-deflate;
之后的 qa
中也有尾随 space 但本地没有。
更新 2
在 Microsoft Edge (Windows 10) 的 qa
环境中一切正常 我还没有尝试过 Internet Explorer 11,但我不得不假设它可能也有效。 OSX 上的 Firefox 和 Chrome 不工作。
更新 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
我已经找到了解决方案,尽管它并不像我希望的那样令人满意。
在我们项目的 pom.xml
中,我们有 spring-core:4.2.5
,但 spring-websocket
和 spring-messaging
是 4.1.6
。版本不匹配显然导致了一些问题。
当版本 不匹配 时,在 Tomcat 启动选项中设置 -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true
无效。当版本相同时设置该 JVM 选项按预期工作。
101
响应现在不包含 permessage-deflate
并且 websockets 能够通过 IIS 毫无问题地连接。我们的应用程序不会通过套接字发送大量数据,因此我们可以做出这种权衡。
在使用ARR3 的Tomcat7 和IIS8 上出现同样的问题。我们没有使用 Spring 个库。
如果启用了 websocket-extensiones,则在建立 websocket 连接后不会发送任何帧。但是如果我们禁用 websocket-extensions 那么一切都会完美。
我遇到了同样的问题。 解决方法是使用 ARR 从客户端覆盖 Websockets 压缩处理 header。 IE 不会强制或尝试 Websocket 压缩,但 Chrome 和 Firefox 将发出带有 Header "Sec-WebSocket-Extensions: permessage-deflate".
的请求由于我无法影响我的 NodeJS 后端服务器,我不得不在 ARR 中解决这个问题。
看看这篇文章。
它对我有用。
修改后,Header 在我的入站重写规则中被空白值覆盖,ARR 处理 Websocket 请求和响应没有问题,因为它们没有被压缩,ARR 可以处理它们在 IIS 中激活 Websockets 模块。
我们在 Tomcat 前面的 Azure AD 应用程序代理遇到了同样的问题。我们必须在 Tomcat.
中禁用 Sec-WebSocket-Extensions