世界上最伟大的投资就是投资自己的教育

首页服务器部署
随风 · 练气

部署之使用 mina 来部署 Ruby on Rails 应用之 websocket (十)

随风发布于2944 次阅读

1. 介绍

在 rails 5 中会释出一个新的 gem,叫actioncable。用这个 gem 可以轻易配合 rails 搭建 websocket 的应用。websocket 是一种协议,一种基于 tcp/ip 的协议,跟 http 协议同等级,它能让客户端与服务器一直保持持久链接。一般来说,在 http 协议中,客户端向服务器请求完资源后就会断开链接的,所以这个时候,他们两者不再保持联系,要联系就要发起另一个请求。但是经常有这样的需求,客户端需要时时与服务器保持通话状态,因为这样,一旦服务器端有消息就可以马上通知客户端,客户端接收到消息后就可以做出相应的应答,比如显示提醒等 。聊天室,股票更新等应用就特别需要这样,以前是用长链接,commet 技术来解决的。这种是在一般的手段上,比如 ajax,不断地发起 ajax 来实现保持通话,这样相当消耗资源,而 websocket 是底层协议的支持,是更好的实现。

在使用 actioncable 这个 gem 的时候,webscoket 的服务器是开在独立于 web 的进程中。而 puma 就支持 websocket,能用它来当 websocket 的服务器。所以我们需要部署 puma 的 websocket 服务器。

在本地测试和使用 actioncable 的时候,建立 websocket 的服务器是用下面这个指令的。

bundle exec puma -p 28080  cable/config.ru

也就是说,我们要把这个指令产生的效果和 nginx 结合搬到服务器主机上。而且我们在每次部署自动控制这个服务器的重启。

2. 使用

首先还是得先部署 puma 的服务,再来处理 nginx。

2.1 mina-puma 的改造

刚开始会尝试使用mina-puma

你会发现这个过程是失败的。虽说 mina-puma 也是 puma 结合 pumactl 的指令来控制 puma 的启动,重启等。

但是查看下 mina-puma 就会知道,它也没像上面那样使用端口,也没有指令配置文件。

所以我们需要结合我们自己的条件来改造。

config/deploy.rb文件中添加下面的内容。

set :puma_cmd, -> { "#{bundle_prefix} puma" }
set :puma_pid, -> { "#{deploy_to}/#{shared_path}/pids/puma.pid" }
set :puma_state, -> { "#{deploy_to}/#{shared_path}/pids/puma.state" }
set :pumactl_cmd, -> { "#{bundle_prefix} pumactl" }
set :puma_env, -> { fetch(:rails_env, 'production') }
set :pumactl_socket, -> { "#{deploy_to}/#{shared_path}/tmp/sockets/pumactl.sock" }
set :puma_socket, -> { "#{deploy_to}/#{shared_path}/tmp/sockets/puma.sock" }

desc 'Start puma'
task :puma_start => :environment do
  queue! %[
    if [ -e '#{pumactl_socket}' ]; then
      echo 'Puma is already running!';
    else
      cd #{deploy_to}/#{current_path} && #{puma_cmd} -q -d -e #{puma_env} -b 'unix://#{puma_socket}' -S #{puma_state} --pidfile #{puma_pid} --control 'unix://#{pumactl_socket}' #{deploy_to}/#{current_path}/cable/config.ru
    fi
  ]
end

desc 'Stop puma'
task :puma_stop => :environment do
  queue! %[
    if [ -e '#{pumactl_socket}' ]; then
      echo 'Puma is stopping!'
      cd #{deploy_to}/#{current_path} && #{pumactl_cmd} -S #{puma_state} stop
      rm -f '#{pumactl_socket}'
    else
      echo 'Puma is not running!';
    fi
  ]
end

desc 'Restart puma'
task puma_restart: :environment do
  invoke :'puma_stop'
  invoke :'puma_start'
end

也可以把这些内容封装成文件放到 lib 目录,再来 require,不过这不重要。

在 mina 部署重启用应的地方引用就好了。

desc "Deploys the current version to the server."
task :deploy => :environment do
  deploy do
    invoke :'sidekiq:quiet'
    ...

    to :launch do
      ...
      invoke :'puma_restart'
      ...
    end
  end
end

上面的代码显示,还是用 unix socket 来监听,而不用端口。所以接下来,对 nginx 的配置还是跟前面部署 unicorn 差不多,只是多了 websocket 的部分。

2.2 nginx

nginx 中的配置文件是这样的。

upstream tt {
    server unix:/tmp/unicorn_production.sock fail_timeout=0;
}

upstream ws {
    server unix:///home/eason/tt_deploy/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  server_name www.rails365.net;
  root /home/eason/tt_deploy/current/public;

  try_files $uri/index.html $uri @tt;
  location @tt {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://tt;
  }

  location /ws/ {
        proxy_pass http://ws;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
  }

  ...
}

不重要的部分被我省略了,最重要的是location /ws/这部分。其实就多了三行关于 websocket 的配置,很简单。

要测试是否配置成功。可以有两种简单的方法。

第一种是用 chrome 的开发者工具中的 network 部分查看是否有 101 状态码的请求。

第二种是在 chrome 的 console 里测试,比如new WebSocket('ws://www.rails365.net/ws');,如果没报错,返回正常 ,一般就没问题的。有一点需要注意,假如用的是 https,ws 就得改成 wss。

完结。

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
喜欢
统计信息
    学员: 29959
    视频数量: 1996
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top