이 라이브러리는 PHP의 PCNTL 확장에 대한 작고 쉬운 래퍼를 제공합니다. 사용하기 쉬운 API를 통해 다양한 프로세스를 병렬로 실행할 수 있습니다.
우리는 동급 최고의 오픈 소스 패키지를 만드는 데 많은 리소스를 투자합니다. 유료 제품 중 하나를 구매하여 우리를 지원할 수 있습니다.
귀하가 사용하고 있는 당사 패키지를 언급하면서 귀하의 고향에서 엽서를 보내주셔서 진심으로 감사드립니다. 연락처 페이지에서 주소를 확인하실 수 있습니다. 우리는 수신된 모든 엽서를 가상 엽서 월에 게시합니다.
작곡가를 통해 패키지를 설치할 수 있습니다.
composer require spatie/async
use Spatie Async Pool ;
$ pool = Pool:: create ();
foreach ( $ things as $ thing ) {
$ pool -> add ( function () use ( $ thing ) {
/ / Do a thing
})-> then ( function ( $ output ) {
/ / Handle success
})-> catch ( function ( Throwable $ exception ) {
/ / Handle exception
});
}
$ pool -> wait ();
비동기 프로세스를 생성하면 ParallelProcess
인스턴스가 반환됩니다. 프로세스에 다음 이벤트 후크를 추가할 수 있습니다.
$ pool
-> add ( function () {
/ / ...
})
-> then ( function ( $ output ) {
/ / On success , `$output` is returned by the process or callable you passed to the queue .
})
-> catch ( function ( $ exception ) {
/ / When an exception is thrown from within a process , it 's caught and passed here.
})
-> timeout ( function () {
/ / A process took too long to finish.
})
;
$pool
객체에 메서드를 사용하는 대신 async
및 await
도우미 함수를 사용할 수도 있습니다.
use Spatie Async Pool ;
$ pool = Pool:: create ();
foreach ( range ( 1 , 5 ) as $ i ) {
$ pool [] = async ( function () {
usleep ( random_int ( 10 , 1000 ));
return 2 ;
})-> then ( function ( int $ output ) {
$ this -> counter += $ output ;
});
}
await ( $ pool );
하위 프로세스 내에서 Exception
또는 Error
발생하는 경우 ->catch()
메서드에 콜백을 지정하여 프로세스별로 이를 포착할 수 있습니다.
$ pool
-> add ( function () {
/ / ...
})
-> catch ( function ( $ exception ) {
/ / Handle the thrown exception for this child process.
})
;
추가된 오류 핸들러가 없으면 await()
또는 $pool->wait()
호출할 때 상위 프로세스에서 오류가 발생합니다.
Throwable
을 발생시키지 않고 하위 프로세스가 예기치 않게 중지되는 경우 stderr
에 작성된 출력은 상위 프로세스에서 SpatieAsyncParallelError
로 래핑되어 발생됩니다.
catch
함수에 대한 유형 힌트를 통해 개별 오류 유형에 대해 각각 여러 오류 처리기를 제공할 수 있습니다.
$ pool
-> add ( function () {
throw new MyException ( ' test ' );
})
-> catch ( function ( MyException $ e ) {
/ / Handle `MyException`
})
-> catch ( function ( OtherException $ e ) {
/ / Handle `OtherException`
});
예외가 처리되자마자 다른 핸들러가 트리거되지 않습니다.
$ pool
-> add ( function () {
throw new MyException ( ' test ' );
})
-> catch ( function ( MyException $ e ) {
/ / This one is triggerd when `MyException` is thrown
})
-> catch ( function ( Exception $ e ) {
/ / This one is not triggerd , even though `M yException ` extends `E xception `
});
수행 중이던 작업이 하위 프로세스 중 하나에 의해 완료되었기 때문에 풀을 조기에 중지해야 하는 경우 $pool->stop()
메서드를 사용할 수 있습니다. 이렇게 하면 풀이 추가 프로세스를 시작하지 못하게 됩니다.
use Spatie Async Pool ;
$ pool = Pool:: create ();
/ / Generate 10 k processes generating random numbers
for ( $ i = 0 ; $ i < 10000 ; $ i ++) {
$ pool -> add ( function () use ( $ i ) {
return rand ( 0 , 100 );
})-> then ( function ( $ output ) use ( $ pool ) {
/ / If one of them randomly picks 100 , end the pool early .
if ( $ output === 100 ) {
$ pool -> stop ();
}
});
}
$ pool -> wait ();
풀은 중지되면 쓸모 없게 되며 필요한 경우 새 풀을 만들어야 합니다.
기본적으로 풀은 php
사용하여 하위 프로세스를 실행합니다. 다음과 같이 다른 바이너리를 구성할 수 있습니다.
Pool:: create ()
-> withBinary ( ' /path/to/php ' );
클로저를 사용하는 것 외에도 Task
사용하여 작업할 수도 있습니다. Task
하위 프로세스에서 추가 설정 작업이 필요한 상황에 유용합니다. 하위 프로세스는 항상 아무것도 없는 상태에서 부트스트랩되기 때문에 초기화를 원할 가능성이 높습니다. 작업을 실행하기 전에 종속성 컨테이너. Task
클래스를 사용하면 이 작업을 더 쉽게 수행할 수 있습니다.
use Spatie Async Task ;
class MyTask extends Task
{
public function configure ()
{
/ / Setup eg . dependency container , load config , ...
}
public function run ()
{
/ / Do the real work here.
}
}
/ / Add the task to the pool
$ pool -> add ( new MyTask ());
작업의 논리를 캡슐화하고 싶지만 완전한 Task
객체를 생성하고 싶지 않은 경우 호출 가능한 객체를 Pool
에 전달할 수도 있습니다.
class InvokableClass
{
/ / ...
public function __invoke ()
{
/ / ...
}
}
$ pool -> add ( new InvokableClass ( / * ... * / ));
원하는 만큼 풀을 생성할 수 있으며, 각 풀에는 처리할 자체 프로세스 대기열이 있습니다.
풀은 개발자가 구성할 수 있습니다.
use Spatie Async Pool ;
$ pool = Pool:: create ()
/ / The maximum amount of processes which can run simultaneously.
-> concurrency ( 20 )
/ / The maximum amount of time a process may take to finish in seconds
/ / ( decimal places are supported for more granular timeouts ) .
-> timeout ( 15 )
/ / Configure which autoloader sub processes should use.
-> autoload ( __DIR__ . ' /../../vendor/autoload.php ' )
/ / Configure how long the loop should sleep before re - checking the process statuses in microseconds .
-> sleepTime ( 50000 )
;
필요한 확장( pcntl
및 posix
)이 현재 PHP 런타임에 설치되지 않은 경우 Pool
자동으로 작업의 동기 실행으로 대체됩니다.
Pool
클래스에는 플랫폼이 비동기 프로세스를 실행할 수 있는지 확인하기 위해 호출할 수 있는 정적 메서드 isSupported
가 있습니다.
Task
사용하여 프로세스를 실행하는 경우 동기 모드에서 실행될 때 해당 작업의 run
메서드만 호출됩니다.
이 패키지를 사용할 때 표면 아래에서 무슨 일이 일어나고 있는지 궁금할 것입니다.
우리는 PHP에서 하위 프로세스를 생성하고 관리하기 위해 symfony/process
구성 요소를 사용하고 있습니다. 즉석에서 하위 프로세스를 생성함으로써 PHP 스크립트를 병렬로 실행할 수 있습니다. 이러한 병렬 처리는 실제로 서로를 기다릴 필요가 없는 여러 동기 작업을 처리할 때 성능을 크게 향상시킬 수 있습니다. 이러한 작업에 실행할 별도의 프로세스를 제공하면 기본 운영 체제가 해당 작업을 병렬로 실행할 수 있습니다.
프로세스를 동적으로 생성할 때 주의할 점이 있습니다. 한 번에 너무 많은 프로세스가 발생하지 않도록 해야 합니다. 그렇지 않으면 애플리케이션이 충돌할 수 있습니다. 이 패키지에서 제공하는 Pool
클래스는 가능한 경우 프로세스를 예약하고 실행하여 원하는 만큼 많은 프로세스를 처리합니다.
이것이 async()
또는 $pool->add()
수행하는 부분입니다. 이제 await()
또는 $pool->wait()
가 수행하는 작업을 살펴보겠습니다.
여러 프로세스가 생성되면 각 프로세스는 별도의 완료 시간을 가질 수 있습니다. 예를 들어 하나의 프로세스가 있을 수 있습니다. HTTP 호출을 기다려야 하고, 다른 하나는 많은 양의 데이터를 처리해야 합니다. 때로는 코드에 프로세스 결과가 반환될 때까지 기다려야 하는 지점이 있을 수도 있습니다.
이것이 우리가 특정 시점을 기다려야 하는 이유입니다. 즉, 풀의 모든 프로세스가 완료될 때까지 기다려야 합니다. 그래야 아직 완료되지 않은 하위 프로세스를 실수로 종료하지 않고 계속하는 것이 안전하다는 것을 확신할 수 있습니다.
모든 프로세스를 기다리는 것은 모든 프로세스가 완료될 때까지 기다리는 while
루프를 사용하여 수행됩니다. 프로세스가 완료되는 시기를 결정하는 것은 SIGCHLD
신호의 리스너를 사용하여 수행됩니다. 이 신호는 OS 커널이 하위 프로세스를 완료할 때 발생합니다. PHP 7.1부터 신호 수신 및 처리에 대한 지원이 훨씬 향상되어 이 접근 방식이 예를 들어보다 성능이 향상되었습니다. 통신을 위해 프로세스 포크나 소켓을 사용합니다. 여기에서 자세한 내용을 읽을 수 있습니다.
프로세스가 완료되면 해당 성공 이벤트가 트리거되며, ->then()
함수를 사용하여 연결할 수 있습니다. 마찬가지로 프로세스가 실패하거나 시간 초과되면 루프는 해당 프로세스의 상태를 업데이트하고 계속 진행합니다. 모든 프로세스가 완료되면 while 루프는 더 이상 기다릴 것이 없음을 확인하고 중지합니다. 이것은 상위 프로세스가 계속 실행될 수 있는 순간입니다.
우리는 이 패키지의 사용 사례에 대한 자세한 정보를 포함하고 ReactPHP 및 Amp와 같은 다른 비동기 PHP 라이브러리와의 비교를 포함하는 블로그 게시물을 작성했습니다: http://stitcher.io/blog/asynchronous-php.
composer test
최근 변경된 사항에 대한 자세한 내용은 CHANGELOG를 참조하세요.
자세한 내용은 CONTRIBUTING을 참조하세요.
보안 관련 버그를 발견한 경우 이슈 트래커를 사용하는 대신 [email protected]로 메일을 보내주세요.
이 패키지를 무료로 사용할 수 있지만, 귀하의 프로덕션 환경에 적용된다면 귀하가 사용하고 있는 패키지를 언급하면서 고향에서 엽서를 보내주시면 감사하겠습니다.
주소는 Spatie, Kruikstraat 22, 2018 Antwerp, Belgium입니다.
우리는 받은 모든 엽서를 회사 웹사이트에 게시합니다.
MIT 라이센스(MIT). 자세한 내용은 라이센스 파일을 참조하십시오.