2011-12-01 3 views
2

이전에 다뤘던 경우 사과드립니다. 검색을했으나 사용 된 정확한 용어를 모를 수도 있습니다.하나의 어레이를 다루는 여러 "에이전트"

이 프로세스는 PHP로 처리됩니다. 나는 파일 이름의 큰 배열이

:

여기 상황이다. 내가 가지고있는 스크립트는이 파일들을 열고 그들의 내용을 데이터베이스에 입력한다. 이러한 파일을 한 번에 하나씩 처리하는 데 24 시간 이상이 걸리며 이러한 파일은 매일 업데이트됩니다.

하나의 큰 배열을 4 개의 작은 배열로 분할하고 동시 프로세스를 실행하면 24 시간 창이 경과하기 전에 작업이 완료되지만, 파일 크기가 매일 달라지기 때문에 하나 또는 두 개의 프로세스가 다른 프로세스보다 몇 시간 전에 완료되는 경우가 있습니다.

자신의 작업을 마친 후 남은 일을 돕기 위해 소매 선반을 재고있는 사람들 (이전에 그 악몽을 꾼 사람들은 누구입니까?)이 "상담원"이있는 곳의 스크립트를 갖고 싶습니다. 똑같이하십시오. 잘못 될 수 있고, 내가 :-)

$files = array('file1','file2','file3','file4','file5'); 
//etc... on to over 4k elements 

while($file = array_pop($files)){ 

    //Something in here... I have no idea what. 

} 

아이디어를 생각하면 항의 너무 자랑 아니에요 -

는 여기에 내가 알아 낸 것의 몇 가지 기본 요? 4 개의 함수 호출이나 4 개의 루프와 같은 것이 내 마음을 넘어서는 반면, 이전 호출이 끝날 때까지 후속 호출을 수행 할 때까지 기다릴 것이라고 확신합니다.

도움을 주시면 감사하겠습니다. 나는이 하나에 진지하게 붙어있다!

감사합니다.

+0

PHP로이 작업을 수행 하시겠습니까? (C#의 ThreadPool과 같은) 쉬운 멀티 스레딩을 지원하는 언어를 사용하십시오. – CodeZombie

+0

파이썬 ..... 아마 여기 대답은 –

+0

입니다. 제가 가장 익숙한 언어이고, 소스 파일을 가져 오는 코드는 PHP로 작성되었습니다 하지만 웹 사이트 대신 bash 콘솔에서 실행되므로 일부 셸 스크립팅은 전적으로 가능성의 영역 내에 있습니다. – user1075581

답변

2

데이터베이스 기반 메시지 대기열이 확실한 해결책 인 것처럼 보이지만,이 경우에는 과도하다고 생각합니다. 필자는 처리 할 파일을 단일 대기열 디렉토리에 넣은 다음 DirectoryIterator 클래스를 사용하여 스캔합니다.이런 식으로 뭔가 :

while (true) { 
    look in the queue directory for a file 
    if you don't fine one, exit the script, all processing is done 
    if you find one, rename it or move it to a work directory 
    if the rename/move command succeeded, process the file 
    if the rename/move command failed, one of the other threads got it first 
} 

편집 :

노동자를 실행에 관해서는, 당신은 백그라운드에서 PHP 프로세스를 생성하는 간단한 쉘 스크립트를 사용할 수 있습니다

NUM_WORKERS=5 
for WORKER in $(seq 1 ${NUM_WORKERS}) 
do 
    echo "starting worker ${WORKER}" 
    php -f /path/to/my/process.php & 
done 

을 그리고, 크론를 만들 예 : 자정에이 런처를 실행할 수있는 항목 :

0 0 * * * /path/to/launcher.sh 
+0

DB를 처리하기 전에 모든 대상 파일이 하나의 디렉토리에 다운로드됩니다. 그러나 원하는대로 할 수있는 유일한 방법은 셸이 있어야한다는 것입니다. 또는 배경 프로세스 (명령 끝에 &를 추가)를 실행하고 프로세스가 완료되는시기를 결정하여 사용 가능한 "에이전트"에 새 파일을 할당 할 수있는 perl 스크립트입니다. 쉘 스크립팅과 Perl은 지금 저를 넘어 있습니다. 그래도 내 "할일"목록에 있습니다 :-) – user1075581

+0

당신은 이걸로 요원에게 파일을 할당하지 않을 것입니다. 에이전트는 더 많은 파일을 검색하고 처리 할 파일이없는 경우 종료합니다.마스터 스크립트는 4 개의 (또는 10 개의) 에이전트를 시작합니다. –

+0

흠 ... 그래서 이것은 "유통 시설"에 더 가깝습니까? (더 나은 anaogy 부족). 이것은 대상 디렉토리에서 실행됩니다. 대상 디렉토리는 파일의 존재 여부에 대해 네 개의 다른 디렉토리를 검색합니다. 디렉토리가 비어 있으면 디렉토리가 파일을 디렉토리로 이동시킵니다. 이러한 각 폴더는 해당 디렉토리에있는 파일의 내용을 DB에 입력하는 별도의 프로세스로 모니터링됩니다. 내가 가까이 있니? 나는 오늘 아침에 커피가 충분하다고 생각하지 않습니다 ... – user1075581

2

"메시지 대기열"이 필요합니다. 뭔가 같이 beanstalkd

기본적으로 개별 파일 이름을 포함하는 메시지 목록을 만듭니다. 그런 다음 처리 할 일련의 프로세서를 만듭니다. 각 프로세서는 하나의 파일을 처리 한 다음 대기열로 돌아가 처리 대기중인 메시지/파일이 더 있는지 확인합니다.

편집 : 다음은 메시지 대기열을 설명하는 데 도움이되는 비유입니다. 당신의 첫 번째 생각은 휴먼 매니저가 파일 더미를 4 개의 더미로 나누고 4 명의 직원 각각에게 더미를 나누어주는 것과 같습니다. 메시지 대기열은 다음과 같습니다. 관리자는 모든 파일을 테이블에 저장하고 각 직원이 테이블에서 하나의 파일을 가져 와서 처리하도록 지시합니다. 그는 테이블에 더 이상 파일이 없을 때까지 파일을 계속 가져 오는 첫 번째 파일로 작업이 완료되면 알려줍니다. 모든 파일이 완료되면 직원이 집에 갈 수 있습니다.

한 명의 직원이 실제로 큰 파일로 끝나고 소수만 처리 할 수 ​​있으며 다른 직원은 작은 파일을 가져 와서 많은 파일을 처리 할 수 ​​있습니다. 각 직원이 처리하는 수에 상관없이 테이블이 비어있을 때까지 계속 작업 할 것입니다.

+0

내가 필요한 것인지 아닌지를 결정하기 전에이 내용을 더 읽어야합니다. @ alex-howansky는 디렉토리에있는 파일을 처리하는 솔루션을 언급했는데, 이는 이미 제 자리에있는 것과 거의 비슷하지만, 직렬 대신 병렬로 프로세스를 실행하는 코드의 경우에는 여전히 조금 갇혀 있습니다 (따라서 beanstalkd를 더보고 싶은 욕망). – user1075581

+0

"메시지 대기열"은 좋은 검색어입니다. 그것은 일반적인 아이디어이며 beanstalkd에 국한되지 않습니다. 이는 특정 구현입니다. Alex의 대기열 구현을 위해 모든 파일을 대기열 디렉토리로 이동시키는 하나의 PHP 또는 bash 스크립트를 가질 수 있습니다. 그런 다음 그가 제공 한 가상 코드를 따르는 별도의 PHP 스크립트를 시작할 것입니다. 이러한 스크립트는 큐의 파일을 동시에 처리하면서 실행됩니다. 그것은 여전히 ​​"메시지 대기열"이며, 더 간단한 코드 - 스스로 - 버전입니다. –

1

처리 할 파일이 없을 때까지 x 개의 슬레이브 스크립트에 파일 경로를 넘기는 서버 마스터 스크립트. 이렇게하면 모든 슬레이브 스크립트가 계속 실행되며 파일 경로가 요청 될 때 동적으로 전달할 수 있습니다. 이 같은

뭔가 :

master.php

<?php 

    // load the array of files to process (however you do this) 
    $fileList = file('filelist.txt'); 

    // Create a listening socket on localhost 
    $serverSocket = stream_socket_server('tcp://127.0.0.1:7878'); 
    $sockets = array($serverSocket); 
    $clients = array(); 

    // Loop while there are still files to process 
    while (count($fileList)) { 

    // Run a select() call on the existing sockets' read buffers 
    // Skip to next iteration if no sockets are waiting for handling 
    if (stream_select($read = $sockets, $write = NULL, $except = NULL, 1) < 1) { 
     continue; 
    } 

    // Loop sockets with data to read 
    foreach ($read as $socket) { 

     if ($socket == $serverSocket) { 
     // Accept new clients 
     $sockets[] = $clients[] = stream_socket_accept($serverSocket); 
     } else if (trim(fgets($socket)) == 'next') { 
     // Hand out a new file path to the client 
     fwrite($socket, array_shift($fileList)."\n"); 
     if (!count($fileList)) { 
      break 2; 
     } 
     } 

    } 

    } 

    // When we're done, disconnect the clients 
    foreach ($clients as $socket) { 
    @fclose($socket); 
    } 

    // ...and close the listen socket 
    @fclose($serverSocket); 

slave.php 그런 다음 바로 master.php를 시작해야

<?php 

    $socket = fsockopen('127.0.0.1', 7878); 

    while (!feof($socket)) { 

    // Get a new file path from the master 
    fwrite($socket,"next\n"); 
    $path = trim(fgets($socket)); 

    if (is_file($path)) { 
     // Process the file at $path here 
    } 

    } 

, 다음 경우 실행되고 있지만 많은 인스턴스를 시작할 수 있습니다. slave.php으로 처리 할 파일이 없을 때까지 계속 실행됩니다.

분명히 오류 처리는 없지만 시작하기위한 기본 프레임 워크를 제공해야합니다. 이는 경쟁 조건을 피하기 위해 함수 호출 (stream_select()fgets()) 차단에 의존합니다. 이는 사용자의 목적에 충분하거나 충분하지 않을 수 있습니다.

+0

그것은 내가 스스로 혼자서 생각해 낼 수 있었던 것보다 훨씬 현명한 것입니다! 나는 그 개념을 좋아한다! 내가 그것을 밖으로 시험해 볼 수 있기 전에 그것은 조금 일 것이다 - 조금 동안 밖으로 향할 준비하면서. 니스! :-디 – user1075581

관련 문제