我为我们的几个需要websocket rails的web应用程序添加了一些功能。在开发中一切都很好,但我不确定如何在我们的生产环境中部署所有这些,因为它有点复杂。
生产设置:
- 1台服务器用作负载均衡器(Nginx)
- 2台服务器用作web服务器,其中我们的rails应用程序使用Nginx和Passenger运行(两台服务器相同)
- 应用服务器使用的其他几个服务器,但我认为它们与这个问题无关
- 所有站点都在HTTPS上运行
负载均衡器配置
以下是其中一个站点的示例,其他站点具有类似的配置:
upstream example {
ip_hash;
server xx.xx.xx.xx:443;
server xx.xx.xx.xx:443;
}
server {
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/example.chained.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
server_name example.com;
rewrite ^(.*) https://www.example.com$1 permanent;
}
server {
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/example.chained.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
server_name www.example.com;
if ($ssl_protocol = "") {
rewrite ^ https://$server_name$request_uri? permanent;
}
client_max_body_size 2000M;
location /css { root /home/myuser/maintenance; }
location /js { root /home/myuser/maintenance; }
location /img { root /home/myuser/maintenance; }
location /fonts { root /home/myuser/maintenance; }
error_page 502 503 @maintenance;
location @maintenance {
root /home/myuser;
if ($uri !~ ^/maintenance/) {
rewrite ^(.*)$ /maintenance/example.html break;
}
}
location / {
proxy_pass https://example;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Web服务器配置
同样,这里有一个站点的例子,其他站点有类似的配置:
server {
server_name example.com;
rewrite ^(.*) https://www.example.com$1 permanent;
}
server {
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/ssl/example.chained.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
root /var/www/example/public;
server_name www.example.com;
if ($ssl_protocol = "") {
rewrite ^ https://$server_name$request_uri? permanent;
}
client_max_body_size 2000M;
passenger_enabled on;
rails_env production;
passenger_env_var SECRET_KEY_BASE "SOME_SECRET";
}
到目前为止我收集到的信息:
- 我需要启用乘客粘性会话
- 我需要在websocket服务器正在侦听的站点的
server
部分创建一个location
- 我需要覆盖乘客对websocket位置的并发请求,使其不受限制
我的问题:
- 我是否也必须在负载平衡器的配置中启用乘客粘性会话?我猜这只适用于网络服务器
- websocket服务器的
location
部分会是什么样子 - 我是否也必须在负载均衡器上创建websocket
location
部分 - 有粘性会话就足以让各种应用程序和服务器保持同步吗
- 我在每台服务器上都运行着各种应用程序,它们都应该收到相同的通知(套接字消息),所以它们都应该连接到同一个websocket服务器(我猜)。既然websocketrails是它们的gemset的一部分,难道每个应用程序都不会尝试生成自己的websocket服务器吗?如果是这样的话,我该如何防止这种情况发生,并使它们只产生一个,以防还没有运行
正如你所看到的,我对websocket rails在生产中如何与乘客和nginx一起工作感到非常困惑,所以即使你不知道所有的答案,也非常感谢你的任何意见!
更新
我在负载均衡器上尝试了以下操作:
upstream websocket {
server xx.xx.xx.xx:443;
server xx.xx.xx.xx:443;
}
location /websocket {
proxy_pass https://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#also tried with this:
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
}
以及在应用程序服务器上:
location /websocket {
proxy_pass https://www.example.com/websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection Upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#also tried with this:
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
}
在客户端,我连接到urlWebSocketRails('www.example.com/websocket');
,并得到以下错误:
WebSocket connection to 'wss://www.example.com/websocket' failed: Error during WebSocket handshake: Unexpected response code: 404
有什么想法吗?
-
我认为您不需要在负载均衡器上进行乘客粘性会话
-
本博客介绍了NGINX的相关WebSocket配置。如果要将Upgrade和Connection标头传递到rails应用程序,则需要在负载平衡器上以及在web服务器上进行WebSocket配置。