Heroku上Rails7应用通过Sidekiq/Carrierwave传视频到S3失败
排查与解决办法
1. 确认Sidekiq Worker进程已启动
Heroku预发布环境不会默认启动worker dyno,即使Procfile已定义:
- 查看当前进程状态:
heroku ps --app <你的预发布应用名> - 若未启动worker,执行启动命令:
heroku ps:scale worker=1 --app <你的预发布应用名>
2. 检查Sidekiq任务执行状态
通过worker日志定位具体错误:
- 实时查看worker日志:
heroku logs --app <你的预发布应用名> -t -p worker - 常见错误场景:
- 缓存文件无法被worker访问(Heroku多dyno文件系统隔离)
- S3凭证配置冲突或环境变量未加载
- S3 Bucket权限不足
3. 修复CarrierWave缓存存储配置
当前VideoUploader.rb使用本地文件缓存,Heroku多dyno环境下worker无法访问web dyno生成的本地缓存文件,需改为S3缓存:
修改VideoUploader.rb:
class VideoUploader < CarrierWave::Uploader::Base include ::CarrierWave::Backgrounder::Delay # 将本地缓存替换为S3缓存 cache_storage :fog def cache_dir "uploads_cache/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end storage :fog def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end def extension_allowlist %w(mp4 mov avi) end end
同时在carrierwave.rb中添加全局缓存配置:
# carrierwave.rb config.cache_storage = :fog
4. 修复AWS凭证配置冲突
carrierwave.rb中同时设置了密钥和IAM角色,两者会冲突:
- 若使用环境变量存储密钥,将
use_iam_profile设为false:
# carrierwave.rb config.fog_credentials = { provider: 'AWS', aws_access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'), aws_secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'), use_iam_profile: false, # 修改为false region: ENV.fetch('AWS_REGION') }
- 若使用IAM角色(需Heroku AWS IAM Role插件支持),则移除
aws_access_key_id和aws_secret_access_key配置,保留use_iam_profile: true
5. 确保Sidekiq监听指定队列
修改Procfile,明确指定Sidekiq配置文件路径,确保worker监听carrierwave队列:
worker: bundle exec sidekiq -c 2 -C config/sidekiq.yml
重启worker进程:heroku ps:restart worker --app <你的预发布应用名>
6. 验证预发布环境变量
确认预发布环境的AWS相关环境变量配置正确:
执行命令查看:heroku config --app <你的预发布应用名>
检查AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION、S3_BUCKET_NAME是否存在且与生产环境一致。
内容的提问来源于stack exchange,提问作者B B
相关产品推荐
相关产品推荐

