9

我有一个流星应用程序的 apache 代理,而 apache 和流星在两台不同的机器上。我需要它,因为 apache 必须为许多真实网站提供服务,并且由于资源有限,在这台机器上安装流星应用程序并不是一个好主意。

但是,如果我尝试通过代理从外部连接,WebSocket 握手会失败,响应代码为 400“只能升级到 websocket”。当我从局域网内直接连接到流星机器时,一切正常。当 WebSocket 失败时,SockJS/Meteor 会退回到 XHR,但不幸的是,这会在相关应用程序中带来一些错误。所以我真的需要 WebSocket 在大多数情况下工作。

我使用此处提到的补丁修补了我的 apache 安装:https ://stackoverflow.com/a/16998664 看起来进展顺利,但没有任何改变......

我的 apache 代理指令目前如下:

ProxyRequests Off
ProxyPreserveHost On
ModPagespeed Off
<proxy>
Order deny,allow
Allow from all
</proxy>
ProxyPass / http://10.0.2.6:3000/
ProxyPassReverse / http://10.0.2.6:3000/

我什至知道是什么引发了问题。apache 代理弄乱了标头。离开我机器的相关数据包的原始请求标头如下所示:

GET /sockjs/430/minw4r_o/websocket HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: myKey
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: My Agent

当数据包从 apache 代理转发时,如下所示:

GET /sockjs/430/minw4r_o/websocket HTTP/1.1
Host: example.com
Origin: http://example.com
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: myKey
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: My Agent
X-Forwarded-For: 24.xxx.xxx.xxx
X-Forwarded-Host: example.com
X-Forwarded-Server: example.com
Connection: Keep-Alive

所以“升级”被删除,“连接”被改变,所以 websocket 握手失败。现在我可以尝试始终使用 RequestHeader 指令将“升级”设置为“websocket”。然而这感觉不对,我想它会带来其他问题,所以我想知道这个问题是否有真正的解决方案?或者这是来自https://stackoverflow.com/a/16998664的补丁应该解决的问题,而我在应用它时出了点问题?

从我读到的切换到 nginx 可以使这个设置更容易。我会考虑这一点,但如果可能的话,我想用 apache 来做这件事,因为 nginx 会使其他事情变得更加复杂并花费我很多时间。

4

5 回答 5

22

我们将它用于 Apache 和 Apache 背后的 SockJS 应用程序。Apache 正在自动进行 WebSocket 代理,但您必须将方案重写为 ws 否则它会回退到 XHR。但前提是连接是 WebSocket 握手。添加以下内容将解决您的问题:)(注意:将localhost:3000相应更改为您自己的后端 url。

RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^websocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]
于 2014-08-20T12:39:43.223 回答
17

该答案基于 Fatih 的答案。对于发送“升级”以外的连接请求标头(例如“保持活动,升级”)的浏览器,他的解决方案失败了。Firefox 42 就是这种情况。

要解决 Firefox 的问题,请按如下方式更改 apache RewriteCond:

RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]

( ^Upgrade$变为Upgrade$ )

我想将此作为对 Fatih 回答的评论,但我缺乏必要的声誉。

于 2015-12-19T13:03:52.750 回答
10

After reading several answers, posting on the Meteor forum, and a lot of trials here is the whole enchilada that worked for me. The other answers were somewhat incomplete, or at least didn't work for me.

I had to do:

sudo a2enmod proxy_wstunnel 

Also had to add a ProxyPass and ProxyPassReverse and changed ^Upgrade$ to Upgrade$ from another SO answer.

<VirtualHost *:80>
    ServerName  some-domain.com

    RewriteEngine on
    RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
    RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
    RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]

    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

</VirtualHost>

then restart Apache.

I checked on the console and there is no error now and no xhr requests. So I assume it's working correctly

于 2016-04-28T23:18:09.007 回答
1

我希望我能够用 apache 指令直接回复你,但既然你提到了 nginx,而且事实是,它很难配置,我想考虑一个实际使用 nginx 但可以保护你的替代方案所有的复杂性。

https://github.com/phusion/passenger/wiki/Phusion-Passenger:-Meteor-tutorial上的教程介绍了在有或没有 nginx 的情况下设置Phusion Passenger的步骤(无论如何它在内部使用 nginx)进行多实例生产Meteor 部署可以扩展以利用服务器中的所有内核。

这很简单:

$ cd meteor-app-directory
$ mkdir public tmp
$ passenger start
于 2014-02-25T12:56:15.890 回答
1

Fatih-Arslan对Derwiwie修正案的回答很有魅力。我必须使用的一件事是使用wss而不是ws,因为我的服务仅在 https 中有效。

RewriteEngine on  
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]  
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]  
RewriteRule .* wss://localhost:3000%{REQUEST_URI} [P]
于 2017-09-11T12:55:27.730 回答