2012-10-31 6 views
6

httpで複数のサプライヤにメッセージを送信するシステムを再開発しています。オリジナルはperlスクリプトであり、再開発でもperlを使用する可能性があります。フォークするか、フォークしないのですか?

以前のシステムでは、すべてのパールスクリプトがすべて同時に実行されていましたが、各サプライヤには5つあります。メッセージがデータベースに格納されると、ランダムなスレッド番号(1-5)とサプライヤが選択されて、メッセージが2回処理されないようにし、テーブル/行をロックしないようにしました。さらに、大きなメッセージが送信されている間に発生した小さな送信を、大きなメッセージの送信が遅延させないようにするために、データベースに「Fair Queue Position」フィールドがありました。

時には1分あたりわずか数個のメッセージしか存在しませんが、他の時には数十万個のメッセージがダンプされることがあります。私は、すべてのスクリプトを実行してメッセージを常にチェックしているので、それを実行するためのよりよい方法があるか、古い方法が受け入れ可能かどうかを判断しようとしています。

私の考えることは、トラフィックの量に応じて必要なだけ多くの子プロセスを実行してフォークするというアイデアがありますが、実装する方法がわからないフェアキューイングが維持されている間に、各メッセージが1回だけ処理されるようにします。

親スクリプトがDBを更新して、どの子プロセスがそれを処理するかを示していると思いますが、元の方法よりも効率が悪くなることが懸念されます。フォークコードを書く経験はほとんどありません(私が最後にしたのは約15年前でした)。

メッセージキューを最適に処理する方法に関するご意見やガイドへのリンクがありがとうございます。

+0

Gearmanや他のジョブサーバーを見ましたか? – jshy

答えて

8

あなたはThread :: Queueまたはこれ以外のものを使うことができます:Is there a multiprocessing module for Perl?

古いシステムがこのようにしてPerlで書かれた場合、ほとんどの部分を再利用することができます。

非作業例:

use strict; 
use warnings; 

use threads; 
use Thread::Queue; 

my $q = Thread::Queue->new(); # A new empty queue 

# Worker thread 
my @thrs = threads->create(sub { 
          while (my $item = $q->dequeue()) { 
           # Do work on $item 
          } 
         })->detach() for 1..10;#for 10 threads 
my $dbh = ... 
while (1){ 
    #get items from db 
    my @items = get_items_from_db($dbh); 
    # Send work to the thread 
    $q->enqueue(@items); 
    print "Pending items: "$q->pending()."\n"; 
    sleep 15;#check DB in every 15 secs 
} 
6

RabbitMQのようなメッセージキューサーバーを使用することをお勧めします。

1つのプロセスがキューに入るので、複数のワーカープロセスでキューを使用できます。このアプローチの

利点:

  • 仕事を待っているときの労働者が必要
  • ワーカープロセスがあることを持っていない場合
  • より多くのワーカープロセスを手動で起動することができます(ないビジーウェイト)をブロックしていません特別な親プロセスの子供
  • RabbitMQは、仕事を受け入れる準備ができているすべての労働者の間で仕事を配布します。
  • RabbitMQは、 ACKを返さないでください
  • データベースに作業を割り当てる必要はありません
  • "エージェント"(ワーカー、プロデューサーなど)すべて)あなたはそれを殺すか、または動的数の労働者のダウンアップを拡大するには、他のプロセス

に影響を与えることなく、それを再起動することができることを意味し独立したプロセスである、あなたのようなものを実装することができます

  1. を自動的に労働者を持っています彼らは指定された時間のための作業を取得しない場合は死ぬ
  2. 別のプロセスがキューの長さを監視し、キューが大きすぎるなっている場合はより多くの労働者を生み出す持っ
+0

私が知る限り、これは基本的に元々実装されていたものです。プロデューサはメッセージをデータベースに挿入するWebページであり、キューはDB内のサプライヤとスレッドの組み合わせに相当し、ワーカープロセス(コンシューマ)は常に実行されているperlスクリプトと同等です。しかし、動的スケーリングに関する記事の第2部では、私に考えのための食糧が与えられています。ありがとう! –

+1

キューにデータベースを使用すると、ワーカーはビジー状態(つまりデータベースを定期的にポーリング)する必要があります。メッセージキューサーバーは作業の配布を処理し、ワーカーがブロックする(つまりCPU時間を消費しない)やるべきことがある。 – ErikR

1

私はキューにジョブを追加し、それらを除去するために、あなたのperlスクリプト内の専用ジョブサーバー用beanstalkd、およびBeanstalk::Clientを使用することをお勧めします。

あなたはRabbitMQと比較して簡単にインストールして設定することができます。また、使用可能な作業者にジョブを配布し、失敗したジョブを埋め込んで後で再試行できるようにし、後でジョブをスケジューリングするなどの基本機能を提供します。作業員にとっては、フォークやスレッディングについて心配する必要はありません。利用可能な数のサーバーで、必要なだけ多くのワーカーを起動してください。

RabbitMQまたはBeanstalkは、独自のデータベースバックアップソリューションよりも優れています。これらのプロジェクトは、すでにキューイングに必要な多くの細部を実現しており、実現していない機能を実装しています。また、睡眠やデータベースからの選択と比較して、新しい仕事のポーリングをより効率的に処理する必要があります。

関連する問題