[php] 오래 실행되는 PHP 스크립트를 관리하는 가장 좋은 방법은 무엇입니까?

완료하는 데 오랜 시간 (5-30 분)이 걸리는 PHP 스크립트가 있습니다. 중요한 경우를 대비하여 스크립트는 curl을 사용하여 다른 서버에서 데이터를 스크랩합니다. 이것이 너무 오래 걸리는 이유입니다. 처리하고 다음 페이지로 이동하기 전에 각 페이지가로드 될 때까지 기다려야합니다.

스크립트를 시작하고 완료 될 때까지 기다리면 데이터베이스 테이블에 플래그가 설정됩니다.

내가 알아야 할 것은 스크립트 실행이 완료되기 전에 http 요청을 종료 할 수있는 방법입니다. 또한 PHP 스크립트가이를 수행하는 가장 좋은 방법입니까?



답변

확실히 PHP로 수행 할 수 있지만 백그라운드 작업으로 수행해서는 안됩니다. 새 프로세스는 시작된 프로세스 그룹에서 분리되어야합니다.

사람들이이 FAQ에 대해 동일한 오답을 계속해서 제공하기 때문에 여기에 더 자세한 답변을 작성했습니다.

http://symcbean.blogspot.com/2010/02/php-and-long-running-processes.html

댓글에서 :

짧은 버전은 shell_exec('echo /usr/bin/php -q longThing.php | at now');여기에 포함하기 위해 약간 긴 이유입니다.


답변

빠르고 더러운 방법은 ignore_user_abortphp 에서 함수 를 사용하는 것입니다. 이것은 기본적으로 다음과 같습니다. 사용자가 무엇을하는지 신경 쓰지 말고 완료 될 때까지이 스크립트를 실행하십시오. 이것은 공개 사이트 인 경우 다소 위험합니다 (20 번 시작하면 동시에 20 ++ 버전의 스크립트가 실행될 수 있기 때문입니다).

“깨끗한”방법 (최소한 IMHO)은 프로세스를 시작하고 매시간 (또는 그 이상) cronjob을 실행하여 플래그가 설정되었는지 확인하려는 경우 플래그를 설정하는 것입니다 (예 : db). 설정되어 있으면 장기 실행 스크립트가 시작되고 설정되지 않으면 아무 일도 발생하지 않습니다.


답변

exec 또는 system 을 사용 하여 백그라운드 작업을 시작한 다음 그 작업을 수행 할 수 있습니다.

또한 사용중인 웹을 스크래핑하는 더 나은 방법이 있습니다. 스레드 방식 (한 번에 한 페이지를 수행하는 여러 스레드)을 사용하거나 이벤트 루프를 사용하는 방법 (한 번에 여러 페이지를 수행하는 스레드 하나)을 사용할 수 있습니다. Perl을 사용하는 개인적인 접근 방식은 AnyEvent :: HTTP를 사용하는 것 입니다.

ETA : symcbean여기서 백그라운드 프로세스를 올바르게 분리하는 방법을 설명 했습니다 .


답변

아니요, PHP는 최상의 솔루션이 아닙니다.

Ruby 나 Perl에 대해서는 잘 모르겠지만 Python을 사용하면 페이지 스크레이퍼를 다중 스레드로 다시 작성할 수 있으며 아마도 최소 20 배 더 빠르게 실행될 것입니다. 다중 스레드 앱을 작성하는 것은 다소 어려울 수 있지만 제가 작성한 첫 번째 Python 앱은 다중 스레드 페이지 스크레이퍼였습니다. 그리고 쉘 실행 함수 중 하나를 사용하여 PHP 페이지 내에서 Python 스크립트를 호출 할 수 있습니다.


답변

네, PHP로 할 수 있습니다. 그러나 PHP 외에도 큐 관리자를 사용하는 것이 좋습니다. 전략은 다음과 같습니다.

  1. 큰 작업을 작은 작업으로 나눕니다. 귀하의 경우 각 작업은 단일 페이지를로드 할 수 있습니다.

  2. 각 작은 작업을 대기열로 보냅니다.

  3. 대기열 작업자를 어딘가에서 실행하십시오.

이 전략을 사용하면 다음과 같은 이점이 있습니다.

  1. 장기간 실행되는 작업의 경우 실행 중간에 치명적인 문제가 발생하는 경우 복구 할 수있는 기능이 있으며 처음부터 시작할 필요가 없습니다.

  2. 작업을 순차적으로 실행할 필요가없는 경우 여러 작업자를 실행하여 동시에 작업을 실행할 수 있습니다.

다양한 옵션이 있습니다 (몇 가지에 불과 함).

  1. RabbitMQ ( https://www.rabbitmq.com/tutorials/tutorial-one-php.html )
  2. ZeroMQ ( http://zeromq.org/bindings:php )
  3. Laravel 프레임 워크를 사용하는 경우 AWS SES, Redis, Beanstalkd 용 드라이버와 함께 대기열이 내장되어 있습니다 ( https://laravel.com/docs/5.4/queues ).


답변

PHP가 최고의 도구 일 수도 있고 아닐 수도 있지만 사용 방법을 알고 있으며 나머지 애플리케이션은이를 사용하여 작성됩니다. 이 두 가지 특성은 PHP가 “충분히 좋다”는 사실과 결합되어 Perl, Ruby 또는 Python 대신 PHP를 사용하는 데있어 매우 강력한 사례입니다.

목표가 다른 언어를 배우는 것이라면 하나를 선택하여 사용하십시오. 언급 한 모든 언어가 문제없이 작동합니다. 나는 Perl을 좋아하지만 당신이 좋아하는 것은 다를 수 있습니다.

Symcbean은 그의 링크에서 백그라운드 프로세스를 관리하는 방법에 대한 좋은 조언을 제공합니다.

간단히 말해, 긴 비트를 처리하는 CLI PHP 스크립트를 작성하십시오. 어떤 방식 으로든 상태를보고하는지 확인하십시오. AJAX 또는 기존 방법을 사용하여 상태 업데이트를 처리 할 PHP 페이지를 만듭니다. 킥오프 스크립트는 자체 세션에서 실행되는 프로세스를 시작하고 프로세스가 진행되고 있다는 확인을 반환합니다.

행운을 빕니다.


답변

나는 이것이 백그라운드 프로세스에서 실행되어야한다는 답변에 동의합니다. 그러나 사용자가 작업이 완료되었음을 알 수 있도록 상태를보고하는 것도 중요합니다.

프로세스 시작을위한 PHP 요청을 수신하면 고유 식별자를 사용하여 작업 표현을 데이터베이스에 저장할 수 있습니다. 그런 다음 화면 스크래핑 프로세스를 시작하여 고유 식별자를 전달합니다. 작업이 시작되었으며 최신 상태를 가져 오기 위해 새 작업 ID가 포함 된 지정된 URL을 확인해야한다고 iPhone 앱에 다시보고하십시오. 이제 iPhone 애플리케이션은이 URL을 폴링 (또는 “긴 폴링”) 할 수 있습니다. 그 동안 백그라운드 프로세스는 완료율, 현재 단계 또는 원하는 기타 상태 표시기로 작업 한 작업의 데이터베이스 표현을 업데이트합니다. 완료되면 완료된 플래그를 설정합니다.