並列実行¶
バージョン 1.3 で追加.
Fabric はデフォルトですべてのタスクを 連続 で実行します。(参照 実行ストラテジー ) このドキュメントは per-taskデコレーター、コマンドラインスイッチを使って複数のホストでタスクを 並行 で実行する Fabric のオプションを説明します。
どうなるか¶
Fabric 1.x は完全なスレッドセーフではありません。(一般的な使い方ではタスク関数は他に影響しません)この機能はPythonの multiprocessing モジュールで実装されています。これはそれぞれのホストとタスクコンビネーションで新しいプロセスを作り同時に多くのプロセスが走るのを避けるために任意(設定可能)のスライディングウィンドウを使います。
例えばいくつかのウェブサーバーでウェブアプリケーションのコードを更新してコードが配信されたら(コードの更新が失敗したら簡単にロールバックできる)サーバーをリロードする状況を想像してください。次のFabfileで実行できます:
from fabric.api import *
def update():
with cd("/srv/django/myapp"):
run("git pull")
def reload():
sudo("service apache2 reload")
そして3つのサーバーで連続して実行するには:
$ fab -H web1,web2,web3 update reload
並列実行のオプションを有効にしなければ通常Fabricはこのように実行します:
update
onweb1
update
onweb2
update
onweb3
reload
onweb1
reload
onweb2
reload
onweb3
並列実行を有効(-P
-- 下記参照)にした場合はこのように:
update
onweb1
,web2
, andweb3
reload
onweb1
,web2
, andweb3
うまくいけば利益は明らかです -- もし update
に 5 秒かかって reload
に 2 秒かかるとすると連続タスクでは (5+2)*3 = 21 秒。しかし並列実行では1/3 平均で (5+2) = 7 秒。
使い方¶
デコレーター¶
並列実行の最小 "単位" はタスクなのでこの機能はタスク単位で有効、無効を指定できます。parallel
と serial
デコレーターを使います。例えばこの fabfile:
from fabric.api import *
@parallel
def runs_in_parallel():
pass
def runs_serially():
pass
この方法で実行すると:
$ fab -H host1,host2,host3 runs_in_parallel runs_serially
次のシーケンスで実行します:
runs_in_parallel
onhost1
,host2
, andhost3
runs_serially
onhost1
runs_serially
onhost2
runs_serially
onhost3
コマンドライン・フラグ¶
コマンドラインフラグ -P
や環境変数 env.parallel を使ってすべてのタスクに並行処理を強制することもできます。しかし、どんなタスクも serial
を指定すると設定を無視してシリアルで実行します。
例えば、次の fabfile は上記の実行シーケンスと同じです:
from fabric.api import *
def runs_in_parallel():
pass
@serial
def runs_serially():
pass
このようにすると:
$ fab -H host1,host2,host3 -P runs_in_parallel runs_serially
前述のように runs_in_parallel
はパラレルで runs_serially
はシーケンスで実行されます。
バブルサイズ¶
巨大なホストリストではローカルマシンが同時に実行されるあまりの多くのFabricプロセスのために高負荷になります。このため同時に走るFabricのアクティブプロセスの数を制限するムービング・バブルアプローチを選ぶこともできます。
デフォルトではバブルは使わずすべてのホストでひとつの poolで実行します。この per-taskレベルは parallel
にキーワード引数 pool_size
を与えることや全体的には -z
でオーバーライドできます。
例えば、同時に5つのホストで走らせるには:
from fabric.api import *
@parallel(pool_size=5)
def heavy_task():
# lots of heavy local lifting or lots of IO here
あるいは kwarg pool_size
をスキップして:
$ fab -P -z 5 heavy_task
出力 行単位 対 バイト単位 (Linewise vs bytewise)¶
Fabricのデフォルトの端末への出力モードはバイト単位です。これは リモートプログラムとのやりとり のサポートのためです。これはパラレルモードでは悲惨なことになります。複数のプロセスが端末の標準出力に同時に書き込むかもしれません。
これを避けるためにパラレルが有効なときには自動的に Fabricの linewise output オプションが有効になります。これは上記リンクの Fabricのリモートインターラクティブ機能の便利さの大部分を失うことになりますが、パラレル呼び出しではうまく配置できません。一般的にはフェアな取引きです。
行単位の出力でも複数のプロセスの混乱を避けることはできません。しかしプレフィックス the host-string で少なくとも見分けることができます。
注釈
将来のバージョンでは並行処理のトラブルシューティングを簡単にするためにロギングサポートが改良されるでしょう。