使用AnyEvent的主工作服务器

时间:2011-07-12 11:00:20

标签: perl events asynchronous

我需要编写一个服务器程序,它将打开并保存5个实时Telnet,SSH和各种服务器连接,同时它会监听另一端的JSONRPC调用。

打开和维护5个连接并监听请求时没问题:

# workers:
open_myconnections( 1..5 );
my $w1 = AnyEvent->timer (interval => $seconds, cb => sub { keep_conn_alive(1) });
my $w2 = AnyEvent->timer (interval => $seconds, cb => sub { keep_conn_alive(2) });
...

# now listen for requests
use AnyEvent::JSONRPC::Lite;
# master: 
my $server = jsonrpc_server '127.0.0.1', '4423';
$server->reg_cb(
    queue_up => sub {
        my ($res_cv, @params) = @_;
        my $res = send_params_to_connection_queue( @params ); 
        $res_cv->result($res);
    },
);

但是现在我一直试图找出最好的方法(即非阻塞AnyEvent方式)在5名工人中分配队列,这就是我的函数send_params_to_connection_queue()

任何模块建议都值得赞赏,虽然我试图避免使用POE,因为这应该是非常小的服务器,除非没有其他明智的选择,否则我'通过。

2 个答案:

答案 0 :(得分:3)

在YAPC :: NA 2011,我了解了一个名为ZeroMQ的非常好的排队系统。使用Perl绑定Direct Perl BindingsAnyEvent bindings


                                                |----- ssh worker
JSONRPC-Listener-EventLoop---->QueueingSystem---|----- telnet worker
                                                |----- etc.

答案 1 :(得分:2)

只有你知道什么是“最好的”,但是有一个关于如何做到这一点的一般模式,也许这是你真正的问题。

基本上,你需要一个队列,比如一个数组,它存储所有尚未发送的请求:

我的@queue;

然后,每次要执行请求时,首先将数据推送到队列中,然后调用“调度程序”函数:

sub do_req {       我的($ data,$ cb)= @_;       推@queue,[$ data,$ cb];       调度;    }

日程安排功能的目的是选择一名工人并开火 下一个请求:

子调度程序{       @queue或返回; #与空队列无关

  for my $worker (@workers) {
     if ("$worker is free") {
        my ($data, $cb) = @{ shift @queue };
        $worker->doit (sub {
           &scheduler;
           $cb->(@_); # call original callback
        });
        return;
     }
  }

}

这样做是为了找到一个自由工作者,向它发送请求(“doit”),以及 当它完成后,它再次调用调度程序。

由您决定工人是否“免费”取决于您。例如,你 总是可以选择具有最少数量未完成请求的工作人员。 或者您可以选择一个工作人员,例如,少于5个未完成的请求。 或者无论哪种方式最好。

重要的是,每当一个工人获得自由(因为一份工作) 完成后,再次调用调度程序,为下一个作业排队。

这样你可以对工人施加任意限制,同时不要忘记 关于你需要做的但由于这个限制而无法发送的工作。

这种技术有许多变异,但基本思想始终是 相同:第一个队列的东西,然后有一个你之后调用的函数 排队和完成作业后,应该分配排队 工作

事件发言时,您可能需要发送一个事件 请求:创建/排队新作业/请求时,以及未完成时 工作完成了。