2017-01-19 1 views
3

이것은 첫 번째 Catalyst 앱이며 다음 문제를 해결하는 방법을 모르겠습니다.Catalyst 응용 프로그램에서 장기 실행 프로세스를 관리하는 방법은 무엇입니까?

사용자가 양식에 데이터를 입력하고 업로드를 위해 파일 (최대 100MB)을 선택합니다. 양식을 제출 한 후 실제 계산에는 최대 5 분이 걸리고 결과는 DB에 저장됩니다.

서버 시간 초과를 방지하려면 배경 인에서이 프로세스 (파일 업로드 일 수도 있음)를 실행하고 싶습니다. 사용자에게 어떤 종류의 피드백이 있어야합니다 (예 : "작업이 시작되었습니다"또는 진행률 표시 줄과 같은). 작업이 아직 실행중인 동안 양식을 차단해야합니다. 작업이 완료되면 결과 페이지가 표시되어야합니다.

독서 시간에 비동기 요청, 작업 대기열, 데몬, Gearman 또는 Catalyst::Plugin::RunAfterRequest과 같은 개념을 발견했습니다.

어떻게 할 수 있습니까? 웹 초보자를 도와 주셔서 감사합니다!

추신 : 현재 로컬 응용 프로그램에서 작업은 병렬 : : ForkManager과 병렬로 수행됩니다. 실제 앱의 경우 Amazon EC2와 같은 클라우드 컴퓨팅 서비스를 사용하는 것이 좋습니다. 또는 멀티 코어 서버를 제공하는 호스팅 업체를 찾으십시오.

+3

업로드를 비동기 요청으로 수행하는 것이 타당합니다. 작업 ID를 반환하고 작업이 완료되면 모델에 플래그를 설정하십시오. 그런 다음 페이지를 정기적으로 (10 초마다) 비동기 적으로 폴링하도록하고 _done_을 얻으면 페이지를 새로 고칩니다. 나는 조금 대답을 타이핑 할 것이다. – simbabque

+0

귀하의 주최자 질문에 관해서는 실제로 유스 케이스에 달려 있습니다. Amazon 또는 기타 클라우드 서비스는 필요한 경우 확장이 용이하다는 이점이 있지만 다른 고려 사항 이외에 자체 서버를 보유하는 것보다 비용이 많이들 수 있습니다. 이 질문은 별개로 또는 다른 곳에 게시하는 것이 가장 바람직합니다. – bytepusher

+0

@simbabque 시간이 있다면 유용한 도구/플러그인이나 몇 가지 예제 코드에 대한 힌트가 매우 유용 할 것입니다. bytepusher에게 감사드립니다. 앱을 제작할 때 고려해 볼 것입니다. –

답변

1

작업을 대기열에 넣고 웹 응용 프로그램 외부의 다른 프로세스에서 수행하십시오. Catalyst 프로세스가 Busy 인 동안 Catalyst :: Plugin :: RunAfterRequest를 사용하더라도 다른 웹 요청을 처리하는 데 사용할 수 없습니다.

매우 간단한 큐 시스템이 있습니다 (예 : File::Queue). 기본적으로 작업 ID를 문서에 할당하고 대기열에 넣습니다. 다른 프로세스가 대기열을 확인하고 새 작업을 선택합니다.

데이터베이스 또는 웹 응용 프로그램에 액세스 할 수있는 모든 작업 상태를 저장할 수 있습니다. 프런트 엔드에서는 X 초 또는 분 단위로 작업 상태를 폴링하여 사용자에게 피드백을 제공 할 수 있습니다.

얼마나 많은 메모리와 CPU가 필요한지 알아 내야합니다. 여러 프로세스가 실행중인 경우에도 다중 코어 CPU 또는 여러 CPU가 필요하지 않을 수 있습니다. EC2와 같은 전용 서버 또는 클라우드 사이에서 선택하는 것은 가격 대비 유연성 (크기 조정, 스냅 샷 등)에 대한 것입니다.

+0

이것은 내가 말하려고했던 것입니다. – simbabque

+0

당신의 충고에 감사드립니다. 줄리앙. Perl을 "복잡한"웹 앱에 사용하는 것에 익숙하지 않습니다. 나는 File :: Queue를 어떻게 사용 하는지를 알 수 없었다. Catalyst에서 대기 및 폴링에 대한 몇 가지 예제 코드를 작성 하시겠습니까? 그 외에도 TheSchwartz를 사용하여이 승인을 적용 할 수 있다고 생각합니까? http://fayland.me/perl/2007/10/04/use-theschwartz-job-queue-to-handle/? –

+0

File :: Queue의 문서에는 예제가 있습니다. http://search.cpan.org/perldoc?File%3A%3AQueue – Julien

1

어떻게 든 File :: Queue에 대한 아이디어를 얻을 수 없었습니다. 비 차단 병렬 실행을 위해 TheSchwartz과 Parallel :: Prefork의 조합을 사용하여 마치 Foorum Catalyst App에 구현 된 것처럼 종료되었습니다. 기본적으로 5 가지 중요한 요소가 있습니다. 어쩌면이 요약은 다른 사람들에게 도움이 될 것입니다.실제 작업이 이루어집니다 TheSchwartz 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) 작업 근로자 (대한

1) TheSchwartz DB

2) 클라이언트 (DB 핸들))

package MyApp::TheSchwartz::Worker::Test; 

use base qw(TheSchwartz::Moosified::Worker); 
use MyApp::Model::DB;  # Catalyst DB connect_info 
use MyApp::Schema;   # Catalyst DB schema 

sub work { 
    my $class = shift; 
    my $job = shift;  
    my ($args) = $job->arg; 
    my ($arg1, $arg2) = @$args; 

    # re-use Catalyst DB schema  
    my $connect_info = MyApp::Model::DB->config->{connect_info}; 
    my $schema = MyApp::Schema->connect($connect_info); 

    # do the heavy lifting 

    $job->completed(); 
} 

4) 테이블을 모니터링하는 작업자 프로세스 TheSchwartzWorker.pl작업 논스톱

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(); 

5)는 촉매 컨트롤러에서 : 테이블 작업에 새 작업을 삽입하고 모든 결과를 사용할 수있을 때까지 새로운 실행은 "아카이브"페이지에서 회색으로 표시됩니다

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")} 
     ) 
    ); 
} 

일부 인수를 전달합니다 데이터베이스에.

관련 문제