使用Action Cable(Puma端口侦听)将Ruby on Rails应用程序部署到Heroku

时间:2015-07-27 03:39:52

标签: ruby-on-rails heroku puma actioncable

我已经在本地主机环境中使用Action Cable,在这种情况下,我使用包含

的简单文件启动Puma服务器
# /bin/bash
bundle exec puma -p 28080 cable/config.ru

一旦发生这种情况,puma服务器就会启动并正在侦听此28080端口以及运行本地服务器的端口。通过在线搜索,我找不到一个地方可以告诉我在heroku上模拟这个或者让我的服务器始终在同一个端口启动的方法(虽然我不知道这是否会给我所需的结果)

我设置了一个javascript文件来创建与该端口相关的消费者。

//= require cable
//= require_self
//= require_tree .


this.App = {};

App.cable = Cable.createConsumer('ws://127.0.0.1:28080');

我想我需要更改127.0.0.1部分以及部署到heroku也能正常工作,但我不确定。我试图切断28080部分并用ENV ['PORT']替换它,但它说这是一个未知的变量,即使我有一个puma.rb文件设置,其端口设置为

... (only part of the file)
rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'
...

所以在我看来ENV ['PORT']被定义为当我检查heroku日志时,puma服务器将

2015-07-26T06:50:25.278030+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 48875 -e production`
2015-07-26T06:50:30.760680+00:00 app[web.1]: => Booting Puma
2015-07-26T06:50:30.760714+00:00 app[web.1]: => Rails 4.2.1 application starting in production on http://0.0.0.0:48875
2015-07-26T06:50:30.760716+00:00 app[web.1]: => Run `rails server -h` for more startup options
2015-07-26T06:50:30.760718+00:00 app[web.1]: => Ctrl-C to shutdown server
2015-07-26T06:50:31.578843+00:00 app[web.1]: Puma 2.12.2 starting...
2015-07-26T06:50:31.578851+00:00 app[web.1]: * Min threads: 0, max threads: 16
2015-07-26T06:50:31.578859+00:00 app[web.1]: * Environment: production
2015-07-26T06:50:31.578861+00:00 app[web.1]: * Listening on tcp://0.0.0.0:48875

如果有任何不清楚的地方我会道歉,如果我遗漏了任何内容,我会很乐意提供更多信息。

修改

以下是/app/assets/javascripts/channels/index.js.erb中的更新代码

//= require cable
//= require_self
//= require_tree .

this.App = {};

App.cable = Cable.createConsumer('<%= ENV["CABLE_SERVER"] %>');

其中ENV [“CABLE_SERVER”]指向ws://the-action-cable-server.herokuapp.com。此变量存储在rails服务器env变量中。

1 个答案:

答案 0 :(得分:8)

问题

Heroku router有一些限制:它只会侦听端口80和443.换句话说,您无法在任何Heroku应用程序上打开固定端口。在ActionCable服务器的情况下,无法打开固定端口并将websocket流量路由到它。因此Heroku允许这样的事情(我怀疑)或者我们使用解决方法。

解决方法

从actioncable版本0.0.3开始,这是我使用的解决方法。

这个想法是没有一个Heroku应用程序而是两个:一个用于主rails服务器,一个用于ActionCable服务器。两者都可以在端口80(或443)上运行。

从一个代码库运行两个不同的服务器只需要有两个Procfiles:一个用于rails,一个用于action cable。有buildpack来处理这个问题。要使用它,您还需要multi buildpack

假设您有两个名为railsactioncable的Heroku应用程序。

使用以下代码在项目的根目录中创建一个.buildpacks文件:

https://github.com/cantino/heroku-selectable-procfile
https://github.com/heroku/heroku-buildpack-ruby

railsactioncable上,使用BUILDPACK_URL创建一个env var https://github.com/heroku/heroku-buildpack-multi.git

现在,对于Procfiles,我选择保留Procfile以便在当地与领班一起运行所有内容,并创建两个自定义的:Procfile.railsProcfile.actioncable

Procfile.rails中,您描述了所有必需的dynos 除了动作电缆服务器,例如:

web: bundle exec puma -C config/puma/config.rb
clockwork: bundle exec clockwork lib/clockwork.rb
worker: bundle exec rake jobs:work

Procfile.actioncable中,您描述了操作有线电视服务器:

web: bundle exec puma -p $PORT cable/config.ru

请注意,我们正在使用web dyno,它将在端口80(或443)上安装动作电缆服务器。

注意您需要将puma配置文件config/puma.rb移动到自定义位置。我选择config/puma/config.rb。当你在没有任何特定配置文件的情况下启动puma时,config/puma.rb是默认位置,这就是我们在Procfile.actioncable中所拥有的。这可能会导致意外行为(请参阅下面的评论)。

现在,在rails上,使用PROCFILE_PATHProcfile.rails创建一个env var actioncable,使用PROCFILE_PATH创建一个env var Procfile.actioncable

说到env vars,actioncable需要来自rails的所有env变量,这些变量是启动actioncable服务器所必需的,如DATABASE_URL或任何凭据。

现在关键步骤:我们如何将railsactioncable连接在一起?这可以通过使用相同的 Redis实例来完成。 rails会在Redis上发送消息,actioncable会听取他们的意见并采取相应行动。这就是为什么两者都必须针对相同的 Redis实例。如果您使用Heroku Redis,则只需在REDIS_URL rails上设置actioncable相同的值即可。以下是有线服务器cable.yml的配置文件:

production: &production
  :url: <%= ENV["REDIS_URL"] %>
  :timeout: 1
development: &development
  :url: <%= ENV["REDIS_URL"] %>
  :timeout: 1
  :inline: true
test: *development

最后一步是更改javascript文件,以便我们可以控制Action Cable服务器的位置。我们可以使用env var。

来做到这一点

如有必要,请将.js后缀更改为.js.erb

//= require cable
//= require_self
//= require_tree .


this.App = {};

App.cable = Cable.createConsumer('<%= ENV["CABLE_SERVER"] %>');

CABLE_SERVER变量现在可以在本地指向ws://127.0.0.1:28080,在rails上,该值将是actioncable的网址。

现在,您已准备好在railsactioncable上部署代码。

注意事项/缺点

  • actioncable上,如果您有任何客户端身份验证,则无法在examples中使用cookies。您现在有两个Heroku应用程序,他们无法共享cookie。我猜你仍然可以使用多个子域的cookie来workaround
  • 您现在有两个要维护的部署目标。
  • 您需要维护多个Procfiles。
  • 希望随着时间的推移,将有一个更简单的解决方法:)

替代

  • 我们可以使用相同的服务器使用简单的中间件处理正常的Web流量 websocket流量。 Here就是这样。
  • 从rails 5 beta2开始,动作电缆服务器现在也可以与您的主要应用程序一起side-mounted。拥有两台不同的服务器仍然有意义:您可以单独扩展它们。

HTH