6

我正在多服务器环境中部署 Rails 应用程序。该应用程序使用资产管道,并且资产是从 s3 提供的。如果我在部署到的每台服务器上运行 assets:precompile,一切正常(在每个盒子上都会生成所需的 assets/manifest.yml)。

问题是这感觉非常低效。我尝试将其中一台服务器指定为主服务器,并且只在该框上运行 assets:precompile 。现在的问题是其他服务器没有 assets/manifest.yml 的副本。

认为解决方案将涉及找出在所有盒子上共享生成的 assets/manifest.yml 文件的最简单方法。

其他人如何处理这种情况?

谢谢你的帮助。

4

3 回答 3

2

最终通过编写这个上限任务解决了这个问题:

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,但可以完成工作。我们不想在本地进行预编译。

于 2013-10-15T23:48:34.620 回答
0

更好的建议可能是升级到 Capistrano 3(上周发布),它通常更快,并且 Rails 插件更好地模块化。在 gem 中找到的rails/assets扩展capistrano-rails很简单(它不能完全满足您的需求,但它更简单)。您可以使用 gem 进行迁移支持,并将资产管道任务复制/修改到您的项目中,并修改它们以执行您需要的任何操作。

同样在 Capistrano 3 中,您可以通过 获取服务器列表roles(:web),例如,这将返回服务器对象列表,因此您可以编写一个任务,仅限于一个可以访问其他服务器列表的服务器,并执行 rsync通过 LAN(或 WAN)将您的资产同步到您的其他机器。

于 2013-10-16T07:37:10.000 回答
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并上传到所有机器。

于 2020-04-16T18:04:52.547 回答