如何通过Apache HTTP服务器获得Vaadin Push工作?

时间:2013-09-20 13:45:58

标签: apache2 tomcat7 push vaadin atmosphere

我正在尝试将Vaadin 7.1.5推送到Apache Tomcat 7.0.42 + Apache HTTP服务器(2.2.14 with mod_proxy_wstunnel)。

当我直接访问Tomcat时(即http://mydomain:8080/myapp),使用WebSocket的Vaadin应用程序和推送工作正常。当我尝试使用Apache模块mod_proxy和amp;来访问它时出现问题。 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

在需要推送之前,我使用mod_jk将请求从http://mydomain/myapp转发到http://mydomain:8080/myapp。 Apparenly 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时工作正常。我发现Atmosphere抛出了501错误,但我不知道如何调试它。如果我删除了ws代理(因此push使用HTTP而不是WS),我会立即得到“Session expired”错误。

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

3 个答案:

答案 0 :(得分: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&lt; = 9)。我怀疑它与HTTP流媒体有关,作为后备方法..

答案 1 :(得分: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(以及mod_proxy_wstunnel启用)的Apache配置:

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连接器。

答案 2 :(得分: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。