如何通过Apache HTTP服务器使Vaadin Push正常工作?

7
我正在尝试让Vaadin 7.1.5 Push在Apache Tomcat 7.0.42 + Apache HTTP服务器(2.2.14和mod_proxy_wstunnel模块)上工作。
当我直接访问Tomcat(即http://mydomain:8080/myapp)时,Vaadin应用程序和使用WebSocket的push正常工作。问题出现在我尝试使用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/myapp转发到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吗?
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流作为后备方法有关..

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连接器。(因此可以发生流媒体回退)
  • 然后,其他推送请求(websocket)通过mod_proxy_wstunnel发送到nio连接器。
  • 其他请求(非推送)将被发送到ajp连接器。

1
这个解决方案适用于WebSocket和长轮询(以及流式传输)。使用单个HTTP[S] Tomcat连接器,一切都可以正常工作 - 即最终行可以是ProxyPass / http://app.domain.com:8080/。我确实需要在“PUSH”后面删除尾随的“/”。 - Aron

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。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接