如何使用 Puma 和 Foreman 设置零停机时间 Rails 部署

介绍

Puma是一个高效的 Ruby 网页服务器,可以很好地处理 Rack 应用程序(如 Rails)。Puma 使用 threads and/or workers提供兼容性。您可以使用 Puma 的集群模式(使用工人)来部署应用程序而无需停机时间。

在本指南中,我们将使用以下内容:

  • Puma作为我们的Web服务器
  • Foreman来管理我们的应用程序(这不是绝对必要的,但它确实使生活更容易)
  • Capistrano部署(部署指令相当通用,可以很容易地重新应用到其他方法)

此指南假定您已使用已有的 Rails 应用程序,请参阅 Rails Getting Started指南,如果您尚未到达那里。本指南还假定您正在使用 Ubuntu;阅读如何设置它 这里

安装puma

可以通过 RubyGems安装 Puma:

1gem install puma

一旦安装,您可以使用Puma简单地打电话来启动应用程序:

1puma config.ru # or whatever your *.ru file is called

但相反,我们将使用Foreman来管理我们的应用程序。

安裝 Foreman

Foreman 可以通过 RubyGems来安装:

1gem install foreman

使用 Puma 和 Foreman 配置铁路

首先,添加puma和foreman到您的Gemfile:

1# Gemfile
2gem 'puma'
3gem 'foreman'

然后安装:

1bundle install

Foreman 需要一个Procfile,用于指定要运行的进程. 您可以给进程命名,例如webworker,然后您可以使用它来区分要运行的进程类型。

1echo "web: bundle exec puma -e $RAILS_ENV -p 5000 -S ~/puma -C config/puma.rb" >> Procfile

您可以更改端口号为您喜欢的任何东西,我们将使用5000。

 1# config/puma.rb
 2threads 1, 6
 3workers 2
 4
 5on_worker_boot do
 6  require "active_record"
 7  cwd = File.dirname(__FILE__)+"/.."
 8  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
 9  ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"] || YAML.load_file("#{cwd}/config/database.yml")[ENV["RAILS_ENV"]])
10end

重要的是正确配置线程和工人数量,Puma README(https://github.com/puma/puma#configuration)提供了一些建议,如何做到这一点。要在集群模式下运行Puma,您需要至少两个工人**。

1grep -c processor /proc/cpuinfo

或者,你可以根据你正在使用的 滴滴类型来计算。 另外,请注意,每个工人将使用给定的线程数量,所以在上面的配置中,将有最少2个和最多12个线程。

on_worker_boot块建立了ActiveRecord连接,每次一个工人启动(即在部署过程中)。

一旦您配置了您的Procfilepuma.rb,您应该能够运行您的应用程序。

1foreman start

一旦加载,您的应用程序应该在 localhost:5000(或您在Procfile中指定的任何端口)上可用。

部署

Foreman 可以导出到 其他流程管理格式;我们将使用 Upstart,这是 Ubuntu 流程管理器。

1sudo foreman export upstart /etc/init -a puma-test-app -u puma-test-user -l /var/puma-test-app/log

在本例中,puma-test-apppuma-test-user将被相应的应用程序名称和系统用户取代,但我们不想在本地进行此操作 - 我们想要做的是自动创建升级脚本作为部署的一部分,以便我们始终正确启动应用程序,并允许Upstart确保它继续运行。

我们将使用Capistrano来部署。如果您尚未这样做,请通过运行设置您的应用程序以与Capistrano合作:

1capify .

在您的应用程序的 root 目录中,然后在在 `config/deploy.rb 创建的文件中,添加以下内容:

 1# config/deploy.rb
 2set :app_name, "puma-test-app"
 3set :user, "puma-test-user"
 4
 5namespace :foreman do
 6  desc "Export the Procfile to Ubuntu's upstart scripts"
 7  task :export, :roles => :app do
 8    run "cd #{current_path} && #{sudo} foreman export upstart /etc/init -a #{app_name} -u #{user} -l /var/#{app_name}/log"
 9  end
10
11  desc "Start the application services"
12  task :start, :roles => :app do
13    run "#{sudo} service #{app_name} start"
14  end
15
16  desc "Stop the application services"
17  task :stop, :roles => :app do
18    run "#{sudo} service #{app_name} stop"
19  end
20
21  desc "Restart the application services"
22  task :restart, :roles => :app do
23    run "#{sudo} service #{app_name} start || #{sudo} service #{app_name} restart"
24  end
25end

foreman:export任务将更新Ubuntu的Upstart脚本,我们每次部署都将呼叫这个。其他任务将管理Upstart支持的服务。你的Procfile不会定期更改,但如果是,你需要重新启动应用程序服务来注册这些更改;你现在可以这样做,运行:

1cap foreman:restart

然而,在大多数情况下,我们所要做的就是告诉Puma进行阶段性重新启动。 为了做到这一点,我们将使用Capistrano deploy:restart 任务,该任务将自动运行作为标准的Capistrano部署的一部分。

 1namespace :deploy do
 2  task :restart, :roles => :app do
 3    foreman.export
 4
 5    # on OS X the equivalent pid-finding command is `ps | grep '/puma' | head -n 1 | awk {'print $1'}`
 6    run "(kill -s SIGUSR1 $(ps -C ruby -F | grep '/puma' | awk {'print $2'})) || #{sudo} service #{app_name} restart"
 7
 8    # foreman.restart # uncomment this (and comment line above) if we need to read changes to the procfile
 9  end
10end

部署:重新启动任务的第一件事是拨打foreman:export来更新我们的Upstart脚本,然后,我们将SIGUSR1信号发送到Puma的所有运行实例中。它通过找到Puma主流程的进程ID,然后发送相应的信号来做这件事。评论的命令在OS X上找到PID,如果您需要本地测试,这可能有助于保持两者。当Puma收到SIGUSR1信号时,它将开始阶段性重新启动。

如果你需要注册你的Procfile的更改,那么你将不得不打电话给foreman:restart任务. 为此,评论从运行开始的行,并评论foreman.restart行.你不应该定期这样做,因为理想情况下你的Procfile在部署之间将保持相同。

测试

在测试之前,请确保Foreman安装在您的Ubuntu VPS上,使用上面的说明。

如果你还没有,你需要设置你的VPS来与Capistrano合作。首先,为你的Web服务器,存储库等填写config.deploy.rb中的空白,然后通过运行配置你的VPS:

1cap deploy:setup

然后你可以跑:

1cap deploy

在此部署期间,您的应用程序将在您的VPS上作为Ubuntu服务启动。在所有后续部署中,Puma将收到SIGUSR1信号,该信号将触发阶段性重新启动;您应该能够在整个重新启动过程中继续使用您的应用程序。

数据库迁移

因此,您需要确保这两个代码库与现有数据库方案相匹配,如果您需要进行迁移,这可能很困难(如果您需要进行大量迁移,并且需要将网站脱机,则可以通过呼叫新的foreman:stop Capistrano 任务,然后呼叫foreman:start任务,以便稍后重新在线)。

Published At
Categories with 技术
comments powered by Disqus