让 Rails、Heroku、Unicorn、Sidekiq 和 Hirefire 都玩得很好
Making Rails, Heroku, Unicorn, Sidekiq and Hirefire all play nice
我们在 Heroku 上有一个非常复杂的 Rails 设置。
在典型的一天中,我们有大约 10 个带有 Unicorn 的 Web Dynos(每个 2x 和 运行ning 3 个 Unicorn worker)和 15 个 Worker Dynos 运行ning Delayed Jobs,尽管它会波动,所以我们当我们可以节省成本时,使用 hirefire 来扩大和缩小规模。我们的 Postgres 数据库允许 400 个连接。
上周我终于厌倦了我们已经使用了几年的 Delayed::Jobs 队列;我们有一系列作业每 10 分钟 运行 一次,它达到了 运行 所有作业需要 10 多分钟的地步,因此它们的队列将得到备份。我决定转移到 Sidekiq,因为我过去曾用它取得过一些成功。
到目前为止,它运行良好,但我发现我们的网络测功机不太一致。例如,这是我们昨天 3 小时的新遗迹图:
但这是前一周完全相同的时间段的情况:
基本上,在 Sidekiq 之前,我们的工作似乎根本没有影响我们的 web dynos,但现在它们是。我在这里唯一的猜测是,当我们每 10 分钟的作业 运行 时,它们会暂时压倒我们的 postgres 连接,这会减慢网络测功机的速度。这是我能想象的工作会影响网络的唯一方式。
有没有想过如何让它们更加分离,或者它们相互影响更小,我们的网络响应时间更一致?
这是我们的 sidekiq.yml:
---
:concurrency: 5
production:
:concurrency: <%= ENV['WORKER_POOL'] || 15 %>
:queues:
- [instant, 3]
- [fetchers, 2]
- [mailers, 1]
- [fetch_all, 1]
- [moderation, 1]
- [default, 1]
- [reports, 1]
- [images, 1]
- [slack, 1]
还有我们的sidekiq.rb
require 'sidekiq'
Sidekiq.configure_server do |config|
database_url = ENV['DATABASE_URL']
if database_url
pool = ENV['WORKER_POOL'] || 15
new_database_url = "#{database_url}?pool=#{pool}"
ActiveRecord::Base.establish_connection(new_database_url)
end
end
Sidekiq.default_worker_options = { retry: 1 }
我们正在为 sidekiq worker 实例覆盖数据库上的池设置,以便我们可以充分利用并发性。
还有我们的database.yml
production:
database: myapp_production
adapter: postgresql
encoding: unicode
pool: 5
还有我们的unicorn.rb
worker_processes 3
timeout 30
preload_app true
listen ENV['PORT'], backlog: Integer(ENV['UNICORN_BACKLOG'] || 200)
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
我们的 Procfile:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
redis: redis-server
worker: bundle exec sidekiq -e production -C config/sidekiq.yml
我们的雇佣经理设置如下
网址:
工人:
有什么建议吗?
它还有待观察,但一个非常有前途的修复似乎已经为我的 config/database.yml
:
中的 sidekiq 工作人员关闭了 prepared_statements
default: &default
adapter: postgresql
encoding: unicode
pool: 5
prepared_statements: <%= !Sidekiq.server? %>
我们在 Heroku 上有一个非常复杂的 Rails 设置。
在典型的一天中,我们有大约 10 个带有 Unicorn 的 Web Dynos(每个 2x 和 运行ning 3 个 Unicorn worker)和 15 个 Worker Dynos 运行ning Delayed Jobs,尽管它会波动,所以我们当我们可以节省成本时,使用 hirefire 来扩大和缩小规模。我们的 Postgres 数据库允许 400 个连接。
上周我终于厌倦了我们已经使用了几年的 Delayed::Jobs 队列;我们有一系列作业每 10 分钟 运行 一次,它达到了 运行 所有作业需要 10 多分钟的地步,因此它们的队列将得到备份。我决定转移到 Sidekiq,因为我过去曾用它取得过一些成功。
到目前为止,它运行良好,但我发现我们的网络测功机不太一致。例如,这是我们昨天 3 小时的新遗迹图:
但这是前一周完全相同的时间段的情况:
基本上,在 Sidekiq 之前,我们的工作似乎根本没有影响我们的 web dynos,但现在它们是。我在这里唯一的猜测是,当我们每 10 分钟的作业 运行 时,它们会暂时压倒我们的 postgres 连接,这会减慢网络测功机的速度。这是我能想象的工作会影响网络的唯一方式。
有没有想过如何让它们更加分离,或者它们相互影响更小,我们的网络响应时间更一致?
这是我们的 sidekiq.yml:
---
:concurrency: 5
production:
:concurrency: <%= ENV['WORKER_POOL'] || 15 %>
:queues:
- [instant, 3]
- [fetchers, 2]
- [mailers, 1]
- [fetch_all, 1]
- [moderation, 1]
- [default, 1]
- [reports, 1]
- [images, 1]
- [slack, 1]
还有我们的sidekiq.rb
require 'sidekiq'
Sidekiq.configure_server do |config|
database_url = ENV['DATABASE_URL']
if database_url
pool = ENV['WORKER_POOL'] || 15
new_database_url = "#{database_url}?pool=#{pool}"
ActiveRecord::Base.establish_connection(new_database_url)
end
end
Sidekiq.default_worker_options = { retry: 1 }
我们正在为 sidekiq worker 实例覆盖数据库上的池设置,以便我们可以充分利用并发性。
还有我们的database.yml
production:
database: myapp_production
adapter: postgresql
encoding: unicode
pool: 5
还有我们的unicorn.rb
worker_processes 3
timeout 30
preload_app true
listen ENV['PORT'], backlog: Integer(ENV['UNICORN_BACKLOG'] || 200)
before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end
after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT'
end
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end
我们的 Procfile:
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
redis: redis-server
worker: bundle exec sidekiq -e production -C config/sidekiq.yml
我们的雇佣经理设置如下
网址:
工人:
有什么建议吗?
它还有待观察,但一个非常有前途的修复似乎已经为我的 config/database.yml
:
default: &default
adapter: postgresql
encoding: unicode
pool: 5
prepared_statements: <%= !Sidekiq.server? %>