7

我正在尝试让 Vaadin 7.1.5 Push 在 Apache Tomcat 7.0.42 + Apache HTTP 服务器(带有 mod_proxy_wstunnel 的 2.2.14)上工作。

当我直接访问 Tomcat(即http://mydomain:8080/myapp)时,Vaadin 应用程序和使用 WebSocket 推送工作正常。当我尝试使用 Apache 模块 mod_proxy 和 mod_proxy_wstunnel 访问它时,就会出现问题。发生的情况是应用程序挂起,加载指示器变红,并且我在浏览器控制台的推送请求中收到此错误:

HTTP Status 501 - Websocket protocol not supported
type Status report
message Websocket protocol not supported
description The server does not support the functionality needed to fulfill this request.

Apache Tomcat/7.0.42

在需要 Push 之前,我使用 mod_jk 将请求从http://mydomain/myappto转发http://mydomain:8080/myapp。显然 mod_jk 不支持 WebSocket 所以我选择使用 ProxyPass 指令。这是我的 Apache 配置:

ProxyPass               /myapp/PUSH/ ws://localhost:8080/myapp/PUSH/
ProxyPassReverse        /myapp/PUSH/ ws://localhost:8080/myapp/PUSH/

ProxyPass               /myapp/VAADIN/ http://localhost:8080/myapp/VAADIN/
ProxyPassReverse        /myapp/VAADIN/ http://localhost:8080/myapp/VAADIN/
ProxyPass               /myapp http://localhost:8080/myapp
ProxyPassReverse        /myapp http://localhost:8080/myapp

我怀疑 mod_proxy_wstunnel 是罪魁祸首,但显然当我代理http://echo.websocket.org时它工作正常。我发现 501 错误是由 Atmosphere 引发的,但我不知道如何调试它。如果我删除 ws 代理(因此推送使用 HTTP 而不是 WS),我会立即收到“会话已过期”错误。

有谁知道如何正确地将来自 Apache HTTP 服务器的推送请求代理到 Apache Tomcat?

4

3 回答 3

4

我通过确保 ProxyPass(和 ProxyPassReverse)的路径与应用程序的上下文相同并在 tomcat 的 server.xml 配置中创建一个新的 NIO 连接器来解决这个问题:

<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="20000"
           redirectPort="8443"
           proxyName="mydomain"
           proxyPort="80" />

我很确定有一种方法可以使用与应用程序上下文不同的路径,但这对我有用。

更新:请注意,此解决方案不适用于不支持 websocket 的浏览器(例如 IE <= 9)。我怀疑它与作为后备方法的 HTTP 流有关..

于 2013-09-21T09:00:25.487 回答
3

以下是如何使用两个连接器:nio 和 ajp。

Tomcat 配置:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
    connectionTimeout="20000" />

<Connector port="8009" protocol="AJP/1.3" />

带有 mod_rewrite 和 mod_proxy 的 Apache 配置(并启用了mod_proxy_wstunnel ):

RewriteEngine on
RewriteCond %{QUERY_STRING} ^((?!X-Atmosphere-Transport=websocket).)*$
RewriteRule ^/PUSH(.*)$ http://app.domain.com:8080/PUSH$1 [P]

ProxyPass /PUSH ws://app.domain.com:8080/PUSH
ProxyPassReverse /PUSH ws://app.domain.com:8080/PUSH

ProxyPass / ajp://localhost:8009/
  • 首先,每个没有 X-Atmosphere-Transport=websocket 参数的推送请求都使用 http 协议发送到 nio 连接器。(因此可能会发生流式回退)
  • 然后,其他推送请求(websockets)通过 mod_proxy_wstunnel 发送到 nio 连接器。
  • 其他请求(非推送)发送到 ajp 连接器。
于 2014-03-20T07:19:11.600 回答
2

我也遇到了这个问题。以下片段为我做了诀窍:

<Location /vaadinServlet/PUSH>
   Require all granted
   RewriteEngine on
   RewriteCond %{HTTP:UPGRADE} ^websocket$ [NC]
   RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
   RewriteRule .* ws://localhost:8080%{REQUEST_URI} [P]
</Location>

你需要mod_proxy_wstunnel

我将 Apache 2.4.10 和 Vaadin 7.7.3 与 Spring Boot 1.4.2 和 Tomcat 8.5.6 一起使用。

于 2016-12-20T12:01:03.367 回答