2013-06-04 2 views
3

하나의 Perl 스크립트에서 여러 가지 작업을 수행해야합니다. fork 또는 thread을 사용하지 마십시오.Perl로 병렬 프로그램을 작성하는 방법은 무엇입니까?

  1. 작업 A : 서버에 5 초마다 HTTP 요청을 보내십시오. 무한대로 차단해서는 안됩니다. 그리고 만약에 :

    1. 'TASK'를 얻는 경우에, 업무 A는 시간이 걸리는 서브 프로세스를 부를 것이다, 그래서 할당 실행 차단 작업 A의 루프를 피하는 방법?
    2. 'PAUSE', 작업 B 또는 작업 C
  2. 작업 B에서 데이터를 수신 할 때 서버에 뭔가를

  3. 메이크업 POST 요청을 할
  4. 'UPDATE', tell 작업 B를 요청을 일시 정지 : MySQL의 요청 1 분마다 확인하고 결과에 따라, tell 작업 A가 POST 요청을

  5. 작업 C를 할 것입니다 뭔가를 소켓 연결 및 tell 작업 A 또는 B에 동의합니다.

세 개의 병렬 부정 순환 과정과 서로 통신합니다. 어떻게해야합니까?

+2

'fork' 또는 therad의 문제점은 무엇입니까? 그들은 이런 종류의 물건을 위해 디자인되었습니다. – TrueY

+0

대기열을 통한 통신은 오히려 간단하고 선택적으로 비 차단이기 때문에 여기서는 실제로 스레드를 사용합니다. 'fork '한다면 파이프 (연결된 파일 핸들)를 통해 통신 할 수 있습니다. 별도의 스크립트에 각 작업을 넣으면 명명 된 파이프 또는 소켓을 사용할 수 있습니다. 어느 것이 훨씬 더 복잡합니다. 적어도 작업 A의 경우 스레드를 사용하여 논 블로킹 속성을 얻습니다 (예 : 요청을 실행하는 5 명의 HTTP 작업자, 시간 소모적 인 하위 작업자) – amon

+0

작업 A로 1.4를 수행해야하는 이유는 무엇입니까 ??? – ikegami

답변

11

이 디자인은 아무 의미가 없으며 스레드 또는 하위 프로세스를 사용하지 않는 것이 더 바람직하지 않다는 주장은 훨씬 더 적합하지 않습니다.

  • 요청 소스 A : : 서버 매 5 초 웹 요청을

    당신은 요청의 세 가지 소스를 가지고있다.

  • 요청 소스 B : 60 초마다 데이터베이스 요청을 서버에 보냅니다.
  • 요청 소스 C : 소켓에서 요청을 수락합니다.

각 요청 소스에 대한 스레드를 만듭니다. 그들의 작업은 소스가 점검되어야 할 때 검사되도록하기 위해 각 요청 소스를 모니터하는 것입니다. 따라서 이러한 스레드는 실제 작업을 수행하지 않아야합니다. 작업을 수행해야하는 경우 작업을 작업자 스레드에 위임합니다. 그들은 아무것도 POST하지 않습니다. 그들은 데이터베이스에 쓰지 않습니다.

실제 작업 (POST 전송 및 데이터베이스 쓰기 포함)은 하나 이상의 작업자 스레드 (선택 사항)에서 수행됩니다. 작업자 스레드는 세 개의 요청 소스로 채워진 단일 Thread :: Queue 대기열에서 요청을 수신합니다.같은


그래서 코드가 보일 것이다
{ 
    my $request_q = Thread::Queue->new(); 

    my %job_handlers = (
     post => \&post_handler, 
     ... 
    ); 

    for (1..NUM_WORKERS) { 
     async { 
     while (1) { 
      my $job = $request_q->dequeue(); 
      my ($job_type, @args) = @$job; 
      my $handler = $job_handlers{$job_type}; 
       or do { warn("Unknown job type $job_type"); next }; 
      $handler->(@args); 
     } 
     }; 
    } 

    async { poll_web($request_q); }; 
    async { poll_db($request_q); }; 
    accept_connections($request_q); 
} 

대신 스레드 프로세스를 사용하려면

use threads; 
use Thread::Queue qw(); 

use constant NUM_WORKERS => 5; # Tweak this. Can be as low as 1. 

sub poll_web { 
    my ($request_q) = @_; 
    ... init ... 
    while (1) { 
     ... 
     $request_q->enqueue([post => ...]); 
     ... 
    } 
} 

sub poll_db { ... }    # Just like poll_web 

sub accept_connections { ... } # Just like poll_web 

sub post_handler { ... }   # Receives args passed to enqueue 

변경,

use threads; 
,

use forks; 

뿐만 :: 대기열 스레드를 계속 사용.

+0

답변이 업데이트되었습니다. – ikegami

+1

+1은 하나의 질문에 더 적합한 답변을 작성하기 위해 인내심을 가지고 있습니다. 감사. –

관련 문제