2012-10-31 43 views
6

我正在重新開發一個系統,通過http發送消息給衆多供應商之一。原來是perl腳本,很可能重新開發也會使用perl。要叉還是不叉?

在舊系統中,有許多perl腳本同時運行,每個供應商有五個腳本。將消息放入數據庫時​​,會選擇一個隨機線程號(1-5)和供應商,以確保沒有消息被處理兩次,同時避免鎖定表/行。此外,數據庫中還有一個「公平隊列位置」字段,用於確保發送大郵件時不會延遲大郵件發送時發生的小發送。

在某些時候,每分鐘只會有幾條消息,但在其他時候會有潛在的數十萬條消息轉儲。在我看來,像所有的腳本一直在運行和檢查消息的資源浪費,所以我試圖找出是否有更好的方法來做到這一點,或者如果舊的方式是可以接受的。

我現在的想法是有一個腳本根據需要運行多少子進程並根據需要分配儘可能多的子進程(但最大限度),但我不確定如何最好地實現它使得每個消息只處理一次,而公平排隊得到維護。

我現在最好的猜測是,父腳本更新數據庫以指示哪個子進程應該處理它,但是我擔心這會比原來的方法效率低。我幾乎沒有寫分叉代碼的經驗(上次我做了大約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這樣的消息隊列服務器。

一個進程將工作饋送到隊列中,並且可以讓多個工作進程使用隊列。這種方法的

優點:

  • 等待工作(沒有忙等待),如果需要的話
  • 工作進程不必是
  • 更多的工作進程,可以手動啓動當工人封鎖一個特殊的父母過程的孩子
  • RabbitMQ將把工作分配給所有準備接受工作的工人
  • 如果工人工作,RabbitMQ將把工作放回隊列不會返回ACK
  • 您不必在數據庫中分配工作
  • 每個「代理人」(工作人員,生產者等))是一個獨立的過程,這意味着你可以殺死它或重新啓動它,而不會影響其他進程

能夠動態地擴展,向上或向下的工人,可以實現類似:

  1. 自動擁有工人如果他們不爲指定的時間量獲得工作模具
  2. 有另一個進程監視隊列的長度,如果隊列變得太大產生更多的工人
+0

據我所知,這基本上是最初實施的。生產者是將消息插入數據庫的網頁,這些隊列相當於數據庫中供應商和線程的組合,並且工作進程(消費者)等同於每次運行的每個perl腳本。然而,關於動態縮放的帖子的第二部分給了我一些思考。謝謝! –

+1

如果您使用數據庫作爲隊列,那麼您的工作人員將不得不忙於等待(即定期輪詢數據庫)。消息隊列服務器將處理工作分配並允許工作人員阻止(即不消耗CPU時間),直到有工作要做。 – ErikR

1

我會建議使用在你的Perl腳本beanstalkd有專門的工作服務器,並Beanstalk::Client添加作業隊列並刪除它們。

與RabbitMQ相比,您應該更容易安裝和設置beanstalkd。它還將負責在可用的工作人員之間分配工作,掩埋任何失敗的工作,以便稍後重試,安排稍後完成的工作以及更多基本功能。對於你的工人,你不必擔心分叉或穿線;只需要儘可能多的服務器啓動儘可能多的服務器。

RabbitMQ或Beanstalk會比自己的db-backed解決方案更好。這些項目已經制定了排隊所需的許多細節,並實現了您可能還沒有意識到的功能。他們還應該更有效地處理新工作的輪詢,而不是睡覺並從數據庫中選擇,以查看是否有更多工作要做。