Capistrano3で並列制御を行う
Capistranoでは、デフォルトではすべてタスクが並列で実行されるようになっていますが、次の設定で並列実行できるサーバの数を制御できます。
設定方法
- タスク個別に設定する場合
task :uptime do on roles(:all), { in: :groups, limit: 5, wait: 2 } do execute :uptime end end
この場合は、5台ずつ実行し、間2秒待機ということになります。 例えば、全部10サーバ実行するとしたら、10サーバのうち5台タスクが実行される => 2秒待ち => 残り5台タスクが実行される という流れになります。
- デフォルトを変更する場合
SSHKit.config.default_runner_config = { in: :groups, limit: 5, wait: 2 }
設定の内容は上記と同じです。 個別にタスクが設定されている場合は、そちらが優先されます。
デプロイタスクで使えるか?
以前、10台を超えるようなアプリケーションサーバへデプロイした際に、クライアントのオープンできるファイルディスクリプタの上限を超えてしまいデプロイができないという問題がありました。 その際は、ファイルディスクリプタの上限値を上げて対応しましたが、根本的な対応として並列で実行できるサーバの数を調整して対応できないかを調べてみました。
結果的には、deploy:publishing
のタスク(currentディレクトリの切り替え)
https://github.com/capistrano/capistrano/blob/96fdb4c8c54772fa6d5a4ed29cc6df8a2f65ee7b/lib/capistrano/tasks/deploy.rake#L99-L107
にかかる時間差がgroupごとに発生してしまうため、このままだと、これが許容できる場合はOK。できない場合はNGとなります。
ほとんどのケースでは、アプリケーションを同時に反映して欲しいのでほぼNGでしょう。
対策として、
Rake::Task["deploy:symlink:release"].clear namespace :deploy do namespace :symlink do desc "Symlink release to current" task :release do on release_roles(:all), in: :parallel do tmp_current_path = release_path.parent.join(current_path.basename) execute :ln, "-s", release_path, tmp_current_path execute :mv, tmp_current_path, current_path.parent end end end end
こういう感じで、上書きしてあげればよさそうですが、ちょっと無理矢理感が強いので避けたい気持ち・・・ アップデートで内容が変わる可能性もありますし。 何か解決できる案があれば教えてください。
参考: https://github.com/capistrano/sshkit#parallel http://asobo.hatenablog.jp/entry/2016/01/17/115631 http://blog.livedoor.jp/sonots/archives/39007111.html