0

我正在尝试使用Twiggy::Server(这意味着一个 plack 应用程序)编写一个基于 perl 的网络服务器。我想通过运行一些可能耗时的子例程来响应对某些数据的请求(来自网页上的 ajax 调用),该子例程生成数据,然后将其转换为 JSON 字符串以返回到客户端网页。

您可以在此处查看我的服务器的精简测试版本:http: //pastebin.com/iNaDTVwL 该示例显示了我在当前实现中面临的问题;用于AnyEvent::ForkManager执行非阻塞部分会导致截断“大”json 响应。

该文档将完美地回答我的问题(并更好地解释我正在尝试做的事情):https ://github.com/jjn1056/Example-PlackStreamingAndNonblocking ...如果它完成了。我只是错过了做非阻塞的“正确”方式,而不是使用AnyEvent::ForkManager它看起来有点像黑客。

4

2 回答 2

1

我个人会使用Net::Async::HTTP::Server::PSGI. 从它的概要:

use Net::Async::HTTP::Server::PSGI;
use IO::Async::Loop;

my $loop = IO::Async::Loop->new;

my $httpserver = Net::Async::HTTP::Server::PSGI->new(
   app => sub {
      my $env = shift;

      return [
         200,
         [ "Content-Type" => "text/plain" ],
         [ "Hello, world!" ],
      ];
   },
);

$loop->add( $httpserver );

$httpserver->listen(
   addr => { family => "inet6", socktype => "stream", port => 8080 },
   on_listen_error => sub { die "Cannot listen - $_[-1]\n" },
);

$loop->run;

显然,这个特别小的例子没有展示任何异步,但是您可以完全访问所有IO::Async系统,以便稍后延迟和响应。

于 2014-07-10T16:10:10.417 回答
0

因此,从评论开始 - 我对您使用的东西知之甚少,无法给您一个具体的回应,但可以提供一些通用的东西。

使用线程来“异步”你的 Perl 脚本的一部分:

#!/usr/bin/perl

use strict;
use warnings;

use threads;
use Thread::Queue; 

my $input_q = Thread::Queue -> new();
my $success_q = Thread::Queue -> new(); 
my $failure_q = Thread::Queue -> new();

my $thread_count = 4; 

sub spinoff_thread {
    while ( my $target = $input_q -> dequeue() )
    {
       #do something to $target
       my @results = `ping -c 10 -i 1 $target`;
       if ( $? ) { 
           $failure_q -> enqueue ( $target );
       }
       else {
           $success_q -> enqueue ( $target );
       }
    } 
}

#main bit

for ( 1..$thread_count ) {
    my $thr = threads -> create ( \&spinoff_thread );
}

foreach my $server ( "server1", "server2", "server3", "server4", "server5" ) {
  $input_q -> enqueue ( $server );
}

$input_q -> end(); #will cause threads to 'bail out' because that while loop will go 'undef'); 

 #wait for threads to complete. 
foreach my $thr ( threads -> list() ) {
   $thr -> join();
}


print "Fail:\n", join ("\n", $failure_q -> dequeue() ), "\n";
print "Success:\n"; join ( "\n", $success_q -> dequeue() ), "\n";

关键点是您的线程 - 基本上是子例程 - 并且可以使用队列来回传递事物。end队列是处理告诉线程终止的好方法 - 当然还有其他方法。

于 2014-07-10T10:25:45.300 回答