使用资产管道优化rails app到多个服务器的部署

时间:2013-10-15 21:59:02

标签: ruby-on-rails ruby deployment capistrano asset-pipeline

我正在多服务器环境中部署rails应用程序。该应用程序使用资产管道,资产从s3提供。如果我在我部署的每台服务器上运行资产:预编译,一切正常(每个框都生成所需的资产/ manifest.yml)。

问题是这种效率非常低。我尝试将其中一个服务器指定为主服务器,并且仅运行资产:在该框上预编译。现在的问题是其他服务器没有assets / manifest.yml的副本。

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

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

感谢您的帮助。

3 个答案:

答案 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文件,该文件负责获取计算机上的最新资产,并将其上传到所有计算机。