该问题的解决方法是配置 Active Storage 应用程序。对于 ActiveRecord 应用程序,它需要使用 queuing 系统而不是默认的 async adapter。这里使用 Sidekiq 做演示:
首先在 Gemfile 中加入 Sidekiq:
gem 'sidekiq'
接着,在 config/application.rb 中,修改 Queueing Handler 为 Sidekiq:
require 'sidekiq'
config.active_job.queue_adapter = :sidekiq
并且,在 config/routes.rb 中,需要配置 Active Storage 的路由:
Rails.application.routes.draw do
# Other routes...
# Serve websocket cable requests in-process
# mount ActionCable.server => '/cable'
# Active Storage routes
match "/rails/active_storage/*path", to: "active_storage/blobs#show", via: :get
end
最后,在 config/environments/production.rb 中设置 cdn_host 并开启出错时自动重试:
config.active_storage.service = :amazon
# CDN Host for Active Storage
config.active_storage.service_url_expires_in = 1.year
config.active_storage.service_urls_expire_in = 120.minutes
config.action_controller.asset_host = Proc.new { |source|
"https://cdn.mydomain.com" if source.start_with?("/rails/active_storage")
}
# Retry up to 5 times with exponential backoff and an initial delay of 1 second
config.active_storage.resolve.purge_through_use_error_handler = true
config.active_storage.resolve.purge_retries = 5
config.active_storage.resolve.purge_backoff_seconds = 1
这些设置可以有效地解决 ActiveStorage::PurgeJob called under high throughput 这个问题。