我正在多服务器环境中部署rails应用程序。该应用程序使用资产管道,资产从s3提供。如果我在我部署的每台服务器上运行资产:预编译,一切正常(每个框都生成所需的资产/ manifest.yml)。
问题是这种效率非常低。我尝试将其中一个服务器指定为主服务器,并且仅运行资产:在该框上预编译。现在的问题是其他服务器没有assets / manifest.yml的副本。
我认为解决方案将涉及找出在所有方框上共享生成的assets / manifest.yml文件的最简单方法。
其他人如何处理这种情况?
感谢您的帮助。
答案 0 :(得分:1)
通过编写此上限任务结束解决此问题:
task :assets_precompile, { on_no_matching_servers: :continue, only: { primary: true } } do
transaction do
on_rollback do
notification.exception_deploy
end
run "cd #{current_release} && RAILS_ENV=#{stage} rake assets:precompile"
# sync manifest.yml
download("#{current_release}/public/assets/manifest.yml", "/tmp/manifest.yml")
find_servers().each do |current_server|
run_locally "ssh app@#{current_server.host} 'mkdir -p #{current_release}/public/assets'"
run_locally "scp /tmp/manifest.yml app@#{current_server.host}:#{current_release}/public/assets/manifest.yml"
end
end
end
看起来有点hacky,但完成工作。我们不想在本地进行预编译。
答案 1 :(得分:0)
更好的建议可能是升级到Capistrano 3(上周发布),它通常更快,并且rails插件更好地模块化。在rails/assets
gem中找到的capistrano-rails
扩展名很简单(它不能满足您的需求,但它更简单)。您可以使用gem进行迁移支持,并将资产管道任务复制/修改到您的项目中,并修改它们以执行您需要的任何操作。
同样在Capistrano中,您可以通过roles(:web)
获取服务器列表,例如,它将返回服务器对象列表,因此您可以编写一个任务,仅限于一个可以访问该列表的服务器其他服务器,并通过LAN(或WAN)执行rsync,以将资产同步到其余计算机。
答案 2 :(得分:0)
task :copy_assets_manifest do
next unless roles(:web, :app).count > 1
manifest_contents, manifest_name = nil, nil
assets_path = release_path.join('public', fetch(:assets_prefix))
on roles(fetch(:assets_roles)), primary: true do
manifest_name = capture(:ls, assets_path.join('manifest*')).strip
manifest_contents = download! assets_path.join(manifest_name)
end
on roles(:app) do
execute :rm, '-f', assets_path.join('manifest*')
upload! StringIO.new(manifest_contents), assets_path.join(manifest_name)
end
end
在计算机上编译资产,然后下载manifest.json文件,该文件负责获取计算机上的最新资产,并将其上传到所有计算机。