3

我必须在一个 Perl 脚本中完成多项任务。最好不要使用forkor thread

  1. 任务 A:每 5 秒向服务器发出一次 HTTP 请求。无穷大,不应被阻塞。如果得到:

    1. 'TASK',任务A会调用一个耗时的子进程,那么如何避免赋值执行阻塞任务A的循环呢?
    2. 'PAUSE',暂停请求
    3. 'UPDATE',tell任务B做某事
    4. 从任务 B 或任务 C 接收数据时向服务器发出 POST 请求
  2. 任务B:每1分钟发出一次mysql请求,根据结果,tell任务A会做POST请求

  3. 任务C:接受socket连接和tell任务A或B做某事。

三个并行的不定式循环过程,并且会相互通信。我怎样才能做到这一点?

4

1 回答 1

11

这种设计毫无意义,并且声称最好不要使用线程或子进程的说法更没有意义。

您有三个请求来源:

  • 请求源 A:每 5 秒向服务器发出一次 Web 请求。
  • 请求源 B:每 60 秒向服务器发出一次数据库请求。
  • 请求源 C:接受来自套接字的请求。

为每个请求源创建一个线程。他们的工作仅仅是监视每个请求源,以确保在应该检查源时检查它们。因此,这些线程都不应该做任何真正的工作。如果必须执行任务,它们会将工作委托给工作线程。他们不发布任何东西。他们不写入数据库。

实际任务(包括发送 POST 和写入数据库)由一个或多个工作线程(您的选择)执行。工作线程从由三个请求源填充的单个 Thread::Queue 队列接收请求。


所以代码看起来像:

use threads;
use Thread::Queue qw( );

use constant NUM_WORKERS => 5;  # Tweak this. Can be as low as 1.

sub poll_web {
   my ($request_q) = @_;
   ... init ...
   while (1) {
      ...
      $request_q->enqueue([post => ...]);
      ...
   }
}

sub poll_db { ... }              # Just like poll_web

sub accept_connections { ... }   # Just like poll_web

sub post_handler { ... }         # Receives args passed to enqueue

{
   my $request_q = Thread::Queue->new();

   my %job_handlers = (
      post => \&post_handler,
      ...
   );

   for (1..NUM_WORKERS) {
      async {
         while (1) {
            my $job = $request_q->dequeue();
            my ($job_type, @args) = @$job;
            my $handler = $job_handlers{$job_type};
               or do { warn("Unknown job type $job_type"); next };
            $handler->(@args);
         }
      };
   }

   async { poll_web($request_q); };
   async { poll_db($request_q); };
   accept_connections($request_q);
}

如果要使用进程而不是线程,请更改

use threads;

use forks;

但继续使用 Thread::Queue。

于 2013-06-04T06:57:40.227 回答