【问题标题】:Websockets on Tomcat 8 + IIS 8 with ARR 3 are not working带有 ARR 3 的 Tomcat 8 + IIS 8 上的 Websocket 无法正常工作
【发布时间】:2016-01-21 05:53:36
【问题描述】:

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

我们有一个 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 上时,这一切都运行良好。将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 开发工具显示它响应 101 就像它应该做的那样......

我使用本地应用程序服务器(没有 IIS 的 Tomcat 8)尝试了这一切,并且 websocket 工作得很好。 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: websocketConnection: upgrade 也是小写,而当您将 IIS 放在前面时,它是 WebsocketUpgrade

Sec-WebSocket-Extensionsqapermessage-deflate; 之后也有一个尾随空格,但本地没有。

更新 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

【问题讨论】:

  • 你能在 Tomcat 的 websockets 上禁用压缩吗? Sec-WebSocket-Extensions:permessage-deflate;表明它正在被压缩,以我的经验 IIS 没有代理压缩的 websocket。
  • @timmah.faase 我会试一试并报告
  • 所以,我尝试将此选项添加到我的 Tomcat 配置中:-Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true 根据文档应该可以解决问题:If true, disable all built-in extensions provided by the server, such as message compression. 但它似乎没有改变响应标题

标签: java tomcat iis websocket arr


【解决方案1】:

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

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

当版本不匹配时,在 Tomcat 启动选项中设置 -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true 无效。当版本相同时设置该 JVM 选项按预期工作。

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

【讨论】:

  • 我使用的所有 spring 库都是 4.3.6,我也遇到了这个问题。我可以确认禁用 websocket 扩展是有效的,但我必须同意这不是一个非常令人满意的解决方案,因为压缩已经消失了。任何其他解决方案都将受到欢迎。
【解决方案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 模块处理它们。

【讨论】:

    【解决方案3】:

    使用 ARR3 在 Tomcat7 和 IIS8 上出现同样的问题。我们没有使用 Spring 库。

    如果启用了 websocket 扩展,则在建立 websocket 连接后不会发送任何帧。但是,如果我们禁用 websocket-extensions,那么一切都可以完美运行。

    【讨论】:

    • 我想知道我们如何为此提交错误报告 - 这看起来肯定是一个错误!我想知道是否有适用于 IIS 的 Microsoft Connect...
    【解决方案4】:

    我们在 Tomcat 前使用 Azure AD 应用程序代理时遇到了同样的问题。我们不得不禁用 Tomcat 中的 Sec-WebSocket-Extensions。

    【讨论】:

      猜你喜欢
      • 2014-09-02
      • 2016-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-02
      • 1970-01-01
      • 2021-03-25
      • 1970-01-01
      相关资源
      最近更新 更多