2013-02-27 7 views
8

Python RQを使用して、我々は動的にワーカープロセスを管理しようとしています。私たちは次のようである(簡略化された形で)、カスタムビルドワーカースクリプトを使用します。Python RQワーカープロセスを正しくシャットダウンする方法は?

from rq import Connection, Worker 

queues_to_listen_on = get_queues_to_listen_on() 

with Connection(connection = get_worker_connection()): 
    w = Worker(queues_to_listen_on) 
    w.work() 

私たちは、労働者のシャットダウン時に特に興味を持っています。私たちの主な関心事は、シャットダウンする前に現在の作業を終了できるような方法で、ワーカーを正常にシャットダウンする方法です。適切なWorkerオブジェクト上のシグナルハンドラは私たちが必要とするように見えますが、ターミナルで実行されているワーカープロセス上でCTRL+Cを押すこと以外は、少なくとも私が知っている限り、それを放出する方法はないようです。

私はそれを見るように、2つの可能性の高いソリューション(間違いなく、よりがあるかもしれない)がある - 好みの順番で:

  1. プログラムはrqライブラリを使用して、request_stopに信号を送信し、これは正常なシャットダウンをトリガ。
  2. 何らかの方法で正しいプロセスのPIDを取得します(作業中のプロセスかワーカーリスナープロセスかどうかはわかりません)。他の方法を使用して、そのプロセスに適切な信号を送信します。これを行うにはいくつかの方法がありますが、もっと多くの作業が必要になり、問題に他の変数を追加する必要があります(たとえば、Fabricを使ってリモートコマンドやその行に沿って実行するなど)。

この問題を解決するには、より良い方法や同じ目標を達成する別の方法がある場合は、私はあなたの提案を感謝します。

+0

PIDが必要な場合は、実際にはw.pidから取得できます – Borys

答えて

4

オプション1は、デザイン面では優れています。取得、

# WORKER_NAME.py 
import os 

PID = os.getpid() 

@atexit.register 
def clean_shut(): 
    print "Clean shut performed" 

    try: 
     os.unlink("WORKER_NAME.%d" % PID) 
    except: 
     pass 

# Worker main 
def main(): 
    f = open("WORKER_NAME.%d" % PID, "w") 
    f.write("Delete this to end WORKER_NAME gracefully") 
    f.close() 

    while os.path.exists("WORKER_NAME.%d" % PID): 
     # Worker working 

そして、あなたのマスタースクリプトで:

しかし(私があまりにもことを憎む)プロセスを終了するCTRL + Cを使用することのあなたの特定の問題を解決するために、あなたはあなたの労働者のために、次の戦略を使用することができます@Borysの作業者PIDが推奨され、ウォームストップ要求が送信され、正常シャットダウンを確保するためにos.unlink("path/to/WORKER_NAME.%d" % worker_PID)が返されます。

これは、不定ループを実行するワーカーにのみ適用されます。ワーカープロセスが普通のシーケンシャルなワンタイムジョブをブロックするものを呼び出す場合は、何らかのタイムアウト戦略を適用するなど、ブロッキングルーチンからさらに解決する必要があります。

関連する問題