介绍
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
,用于指定要运行的进程. 您可以给进程命名,例如web
和worker
,然后您可以使用它来区分要运行的进程类型。
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连接,每次一个工人启动(即在部署过程中)。
一旦您配置了您的Procfile
和puma.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-app
和puma-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
任务,以便稍后重新在线)。