Perl 如何在Catalyst应用程序中管理长时间运行的流程?

Perl 如何在Catalyst应用程序中管理长时间运行的流程?,perl,asynchronous,cloud,daemon,catalyst,Perl,Asynchronous,Cloud,Daemon,Catalyst,这是我的第一个Catalyst应用程序,我不知道如何解决以下问题 用户在表单中输入一些数据,然后选择一个文件(最大100MB)进行上传。提交表单后,实际计算最多需要5分钟,结果存储在数据库中 我想做的是在后台运行这个过程(可能还有文件上传),以避免服务器超时。应该有一些反馈给用户(比如消息“作业已开始”或进度条)。当作业仍在运行时,应阻止窗体。作业完成后,应显示结果页面 在数小时的阅读中,我偶然发现了异步请求、作业队列、守护进程或其他概念 你会怎么做? 感谢您帮助web开发新手 PS:在我当前的

这是我的第一个Catalyst应用程序,我不知道如何解决以下问题

用户在表单中输入一些数据,然后选择一个文件(最大100MB)进行上传。提交表单后,实际计算最多需要5分钟,结果存储在数据库中

我想做的是在后台运行这个过程(可能还有文件上传),以避免服务器超时。应该有一些反馈给用户(比如消息“作业已开始”或进度条)。当作业仍在运行时,应阻止窗体。作业完成后,应显示结果页面

在数小时的阅读中,我偶然发现了异步请求、作业队列、守护进程或其他概念

你会怎么做? 感谢您帮助web开发新手


PS:在我当前的本地应用程序中,这项工作是与parallel::ForkManager并行完成的。对于真正的应用程序,是否建议使用像AmazonEC2这样的云计算服务?或者找一个提供多核服务器的主机?

将作业放入队列中,并在Web应用程序之外的另一个进程中执行。当您的Catalyst进程繁忙时,即使使用Catalyst::Plugin::RunAfterRequest,它也不能用于处理其他web请求

有非常简单的排队系统,比如。基本上,为文档分配一个作业ID,然后将其放入队列中。另一个进程检查队列并拾取新作业

您可以将作业状态保存在数据库或任何web应用程序可访问的任何内容中。在前端,您可以每X秒或分钟轮询一次作业状态,以向用户提供反馈


你必须计算出你需要多少内存和CPU。即使有多个进程正在运行,也可能不需要多核CPU或多个CPU。选择专用服务器还是像EC2这样的云,更多的是灵活性(调整大小、快照等),而不是价格

不知何故,我无法理解File::Queue。对于非阻塞并行执行,我最终使用了和parallel::Prefork的组合,就像在中实现的一样。 基本上,有5个重要因素。也许这个总结会对其他人有所帮助

(一)

2) TheSchwartz DB的客户端(DB句柄)

package MyApp::TheSchwartz::Client;

use TheSchwartz;    
sub theschwartz {
    my $theschwartz = TheSchwartz->new(
        databases => [ {
            dsn  => 'dbi:mysql:theschwartz',
            user => 'user',
            pass => 'pass',
        } ],
        verbose => 1,
    );
    return $theschwartz;
}
3) 工作人员(完成实际工作的地方)

4) 一个工作进程
TheSchwartzWorker.pl
,它不间断地监视表作业

5) 在Catalyst控制器中:将新作业插入表作业并传递一些参数

use MyApp::TheSchwartz::Client qw/theschwartz/;
sub start : Chained('base') PathPart('start') Args(0) {
    my ($self, $c ) = @_;

    $client = theschwartz();
    $client->insert(‘MyApp::TheSchwartz::Worker::Test’, [ $arg1, $arg2 ]);

    $c->response->redirect(
        $c->uri_for(
            $self->action_for('archive'),
            {mid => $c->set_status_msg("Run '$name' started")}
        )
    );
}

新的运行在“存档”页面上呈灰色显示,直到数据库中的所有结果都可用。

将上载作为异步请求是有意义的。返回作业ID,并在完成操作时在模型中设置标志。然后让您的页面定期异步轮询后端(如每10秒一次),如果完成了轮询,请刷新页面。我将在稍后键入一个答案。关于您的主持人问题,这实际上取决于用例。亚马逊或其他云服务的优势在于,如果需要,可以方便地进行扩展,但除了其他考虑因素外,可能比拥有自己的服务器更昂贵。这个问题最好单独发布在其他地方。@simbabque如果你有时间,提供有用的工具/插件或一些示例代码的提示将非常有用。感谢ByTePuter,我会考虑当应用程序投入生产时,下面的朱利安的答案在纯后端方面是有帮助的。但我们需要知道更多。你说的是并行处理之类的东西。你的申请有学术研究背景吗?因为用户不多,所以需要一段时间可以吗?或者这是一个商业应用程序,应该尽可能快?这是一个用于研究目的的生物信息学应用程序。也许以后也会用于商业用途。基本上,它在一个大文件中搜索文本字符串,提取序列,将结果存储在数据库中,并将其可视化。在初始阶段,该应用程序将主要由1或2人同时使用。无论如何,在我的本地开发环境中,我使用ForkManager的32个线程,因此一次运行大约需要1分钟,这是可以的。如果任务没有并行化,计算量会增加七倍。这也是我要说的。谢谢你的建议Julien。我对使用Perl进行“复杂”的web应用还不熟悉。我不知道如何使用File::Queue。你介意写一些排队和轮询Catalyst的示例代码吗?除此之外,您认为我可以使用schwartz:?doc for File::Queue有以下示例:
use MyApp::TheSchwartz::Client qw/theschwartz/;    # db connection
use MyApp::TheSchwartz::Worker::Test;
use Parallel::Prefork;

my $client = theschwartz();

my $pm = Parallel::Prefork->new({
    max_workers  => 16,
    trap_signals => {
        TERM => 'TERM',
        HUP  => 'TERM',
        USR1 => undef,
    }
});

while ($pm->signal_received ne 'TERM') {
    $pm->start and next;

    $client->can_do('MyApp::TheSchwartz::Worker::Test');    
    my $delay = 10;    # When no job is available, the working process will sleep for $delay seconds
    $client->work( $delay );

    $pm->finish;
}    
$pm->wait_all_children();
use MyApp::TheSchwartz::Client qw/theschwartz/;
sub start : Chained('base') PathPart('start') Args(0) {
    my ($self, $c ) = @_;

    $client = theschwartz();
    $client->insert(‘MyApp::TheSchwartz::Worker::Test’, [ $arg1, $arg2 ]);

    $c->response->redirect(
        $c->uri_for(
            $self->action_for('archive'),
            {mid => $c->set_status_msg("Run '$name' started")}
        )
    );
}