2012-10-31 15 views
6

Tôi đang phát triển lại một hệ thống sẽ gửi tin nhắn qua http đến một trong số một số nhà cung cấp. Bản gốc là các script perl và có khả năng là sự tái phát triển cũng sẽ sử dụng perl.Để ngã ba hay không ngã ba?

Trong hệ thống cũ, có một số tập lệnh perl chạy cùng một lúc, năm cho mỗi nhà cung cấp. Khi một thông điệp được đưa vào cơ sở dữ liệu, một số chuỗi ngẫu nhiên (1-5) và nhà cung cấp đã được chọn để đảm bảo rằng không có thông báo nào được xử lý hai lần trong khi tránh phải khóa bảng/hàng. Ngoài ra, còn có trường "Vị trí hàng đợi công bằng" trong cơ sở dữ liệu để đảm bảo rằng thư gửi lớn không trì hoãn các lần gửi nhỏ đã xảy ra trong khi thư lớn được gửi.

Đôi khi, sẽ chỉ có một vài thư mỗi phút, nhưng vào những lúc khác, sẽ có một bãi chứa hàng trăm nghìn thư. Dường như với tôi như một sự lãng phí tài nguyên để tất cả các kịch bản chạy và kiểm tra các tin nhắn tất cả thời gian nên tôi đang cố gắng tìm ra nếu có cách nào tốt hơn, hoặc nếu cách cũ có thể chấp nhận được.

Suy nghĩ của tôi bây giờ nằm ​​với ý tưởng có một tập lệnh chạy và dồn nhiều tiến trình con là cần thiết (tối đa một giới hạn) tùy thuộc vào lưu lượng truy cập, nhưng tôi không chắc cách tốt nhất để triển khai nó như vậy mà mỗi tin nhắn được xử lý chỉ một lần, trong khi hàng đợi công bằng được duy trì. Hiện tại, tôi đoán tốt nhất là kịch bản gốc cập nhật DB để chỉ ra quy trình con nào sẽ xử lý nó, tuy nhiên tôi lo ngại rằng điều này sẽ kết thúc kém hiệu quả hơn so với phương pháp ban đầu. Tôi có ít kinh nghiệm viết mã giả mạo (lần trước tôi làm nó khoảng 15 năm trước).

Bất kỳ suy nghĩ hoặc liên kết nào đến hướng dẫn về cách xử lý hàng đợi thông điệp tốt nhất!

+0

Bạn đã xem Gearman hoặc bất kỳ máy chủ công việc nào khác không? – jshy

Trả lời

8

Bạn có thể sử dụng Thread :: Queue hoặc bất kỳ khác từ này: Is there a multiprocessing module for Perl?

Nếu hệ thống cũ được viết bằng Perl theo cách này bạn có thể tái sử dụng hầu hết các phần của nó.

Non dụ làm việc:

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

Tôi khuyên bạn nên sử dụng máy chủ xếp hàng thư như RabbitMQ.

Một nguồn cấp dữ liệu quy trình hoạt động trong hàng đợi và bạn có thể có nhiều quy trình công nhân tiêu thụ hàng đợi.

Ưu điểm của phương pháp này:

  • công nhân chặn khi chờ đợi cho công việc (không phải chờ đợi bận rộn)
  • hơn quá trình lao động có thể được khởi động bằng tay nếu cần thiết
  • quá trình lao động không phải là con của một quy trình cha mẹ đặc biệt
  • ThỏMQ sẽ phân phối công việc trong số tất cả công nhân sẵn sàng chấp nhận công việc
  • RabbitMQ sẽ đưa công việc trở lại hàng đợi nếu công nhân làm việc không trả lại ACK
  • bạn không phải chỉ định công việc trong cơ sở dữ liệu
  • mọi "đại lý" (công nhân, nhà sản xuất, v.v.) Là một quá trình độc lập có nghĩa là bạn có thể giết chết nó hoặc khởi động lại nó mà không ảnh hưởng quá trình khác

Để tự động mở rộng quy mô lên hoặc xuống công nhân số, bạn có thể thực hiện một cái gì đó như:

  1. có công nhân tự động chết nếu họ không nhận được công việc trong một khoảng thời gian nhất định
  2. có quá trình khác theo dõi độ dài của hàng đợi và đẻ trứng nhiều người lao động nếu hàng đợi là nhận được quá lớn
+0

Theo như tôi có thể nói, đây là cơ bản những gì đã được thực hiện ban đầu. Các nhà sản xuất là các trang web chèn các thông điệp vào cơ sở dữ liệu, các hàng đợi tương đương với sự kết hợp giữa nhà cung cấp và chuỗi trong DB và các quy trình công nhân (người tiêu dùng) tương đương với mỗi tập lệnh perl đang chạy mọi lúc. Tuy nhiên phần thứ hai của bài viết của bạn về việc mở rộng quy mô động cho tôi thức ăn để suy nghĩ. Cảm ơn! –

+1

Nếu bạn sử dụng một cơ sở dữ liệu cho hàng đợi thì công nhân của bạn sẽ phải chờ đợi (ví dụ: thăm dò ý kiến ​​cơ sở dữ liệu định kỳ.) Máy chủ xếp hàng tin nhắn sẽ xử lý việc phân phối công việc và cho phép nhân viên chặn (tức là không tiêu tốn thời gian CPU) có việc phải làm. – ErikR

1

tôi sẽ khuyên bạn sử dụng beanstalkd cho một máy chủ công việc chuyên dụng, và Beanstalk::Client trong kịch bản perl của bạn để thêm công ăn việc làm cho hàng đợi và tháo gỡ chúng.

Bạn nên tìm beanstalkd dễ cài đặt và thiết lập so với RabbitMQ. Nó cũng sẽ chăm sóc phân phối công việc giữa các công nhân có sẵn, chôn vùi bất kỳ công việc thất bại để họ có thể được thử lại sau đó, lên kế hoạch công việc phải được thực hiện vào một ngày sau đó, và nhiều tính năng cơ bản hơn. Đối với người lao động của bạn, bạn không phải lo lắng về việc gây khó khăn hoặc luồng; chỉ cần khởi động nhiều công nhân như bạn cần, trên nhiều máy chủ như bạn có sẵn.

Hoặc RabbitMQ hoặc Cây đậu sẽ tốt hơn là tung giải pháp được hỗ trợ bởi db của riêng bạn. Các dự án này đã làm việc ra rất nhiều chi tiết cần thiết để xếp hàng và thực hiện các tính năng mà bạn có thể chưa nhận ra mà bạn muốn. Họ cũng nên xử lý bỏ phiếu cho các công việc mới hiệu quả hơn, so với ngủ và chọn từ cơ sở dữ liệu của bạn để xem có nhiều việc phải làm hay không.