你必须使用
FCGI
实施
对待
FCGI_ABORT_REQUEST
.
你
不能
使用以下内容,因为它们忽略了
fcgi_中止请求
:
你
可以使用
以下内容:
对待
fcgi_中止请求
:
使用时
AnyEvent-FCGI
,检查中止的请求与调用一样简单。
$request->is_active()
但请记住
is_active()
在
on_request
处理程序返回,这意味着您必须从返回
单请求
尽快并且以某种方式“并行”完成实际工作(您可能不想使用
Perl threads
但更类似于
continuations
)为了给
AnyEvent
循环处理任何进一步请求的机会(包括
fcgi_中止请求
s)当您完成长距离操作时。
我不太熟悉
任何事件
为了确定是否有更好的方法可以做到这一点,下面是我的看法,首先:
use AnyEvent;
use AnyEvent::FCGI;
my @jobs;
my $process_jobs_watcher;
sub process_jobs {
# cancel aborted jobs
@jobs = grep {
if ($_->[0]->is_active) {
true
} else {
# perform any job cleanup
false
}
} @jobs;
# any jobs left?
if (scalar(@jobs)) {
my $job = $jobs[0];
my ( $job_request, $job_state ) = @$job;
# process another chunk of $job
# if job is done, remove (shift) from @jobs
} else {
# all jobs done; go to sleep until next job request
undef $process_jobs_watcher;
}
}
my $fcgi = new AnyEvent::FCGI(
port => 9000,
on_request => sub {
my $request = shift;
if (scalar(@jobs) < 5) { # set your own limit
# accept request and send back headers, HTTP status etc.
$request.print_stdout("Content-Type: text/plain\nStatus: 200 OK\n\n");
# This will hold your job state; can also use Continutiy
# http://continuity.tlt42.org/
my $job_state = ...;
# Enqueue job for parallel processing:
push @jobs, [ $request, $job_state ];
if (!$process_jobs_watcher) {
# If and only if AnyEvent->idle() does not work,
# use AnyEvent->timer() and renew from process_jobs
$process_jobs_watcher = AnyEvent->idle(cb => \&process_jobs);
}
} else {
# refuse request
$request.print_stdout("Content-Type: text/plain\nStatus: 503 Service Unavailable\n\nBusy!");
}
}
);
AnyEvent->loop;