我正在尝试使用Twiggy::Server
(这意味着plack应用程序)编写一个基于perl的web服务器。我想通过运行一些可能耗时的子例程生成数据,然后将其转换为返回到客户端网页的JSON字符串来响应请求(来自网页上的ajax调用)。
你可以在这里看到我的服务器的精简测试版本:http://pastebin.com/iNaDTVwL这个例子显示了我目前的实现所面临的问题;使用AnyEvent::ForkManager
来做非阻塞部分的事情会导致'big' json响应的截断。
这个文档将完美地回答我的问题(并更好地解释我正在尝试做什么):https://github.com/jjn1056/Example-PlackStreamingAndNonblocking…如果它完成了。我只是错过了做非阻塞的"正确"方式,而不是使用AnyEvent::ForkManager
,这似乎有点黑客。
我个人使用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
系统,以便延迟和稍后响应。
所以从评论来看——我对你使用的东西了解不够,不能给你一个具体的回应,但我可以提供一些一般的东西。
使用线程'async'你的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
队列是处理告诉线程终止的好方法-当然还有其他方法。