문제

사용자 페이지 조회 기록 등을 저장하면서 지속적으로 실행되는 Gearman 작업자가 많이 있습니다.가끔 Gearman 작업자가 사용하는 PHP 코드를 업데이트하겠습니다.작업자가 새 코드로 전환하도록 하기 위해 작업자의 PHP 프로세스를 종료하고 다시 시작합니다.

이를 수행하는 더 좋은 방법은 무엇입니까?아마도 해당 작업자 프로세스 중 하나를 종료하면 데이터(매우 중요한 데이터는 아니지만)가 손실되는 경우가 있을 것입니다.

편집하다:나에게 맞는 답변을 찾아서 아래에 게시했습니다.

도움이 되었습니까?

해결책 3

글쎄, 나는이 질문을 게시했다. 이제 나는 그것에 대한 좋은 대답을 찾았다 고 생각한다.

net_gearman_worker 코드를 보면 작업 루프에서 기능 스톱워크가 모니터링되고 True가 반환되면 기능이 종료됩니다.

나는 다음을했다 :
Memcache를 사용하여 캐시 된 값 인 Gearman_restartTime을 만들었고 별도의 스크립트를 사용하여 사이트를 업데이트 할 때마다 현재 타임 스탬프로 설정했습니다. (Memcache를 사용했지만 데이터베이스, 파일 등 어디에도 저장 될 수 있습니다).

나는 근로자 클래스를 본질적으로 net_gearman_worker_foo로 확장했고, 모든 근로자들이 그것을 인스턴스화하게했다. FOO 클래스에서는 다음을 수행하기 위해 스톱워크 함수를 대체했습니다. 먼저 Gearman_RestArtTime을 확인합니다. 처음으로, 그것은 전역 변수의 값을 절약합니다. 그때부터 매번 캐시 된 값을 전 세계와 비교합니다. 변경되면 스톱워크가 진실을 반환하고 작업자가 종료됩니다. CRON은 매 분마다 각 작업자가 여전히 실행 중인지 확인하고 종료 된 작업자를 다시 시작합니다.

스톱워크에 타이머를 넣고 x 분마다 한 번만 캐시를 확인하는 것이 좋습니다. 우리의 경우, Memcache는 매번 값을 확인하는 것이 문제가되지 않는 것처럼 보이지만, 다른 시스템을 사용하여 현재 타임 스탬프를 저장하는 경우 덜 자주 확인하는 것이 더 나을 것입니다.

다른 팁

해결책 1


일반적으로 나는 -r 깃발을 사용하여 Unix Daemon 유틸리티로 작업자를 운영하고 한 직업 후에 만료됩니다. 각 반복 후에 스크립트가 우아하게 끝나고 데몬은 자동으로 다시 시작됩니다.

당신의 근로자는 한 직업에 대해 부실하지만 데이터를 잃는 것만 큼 큰 거래는 아닙니다.

이 솔루션은 또한 메모리를 확보 할 수있는 이점이 있습니다. PHP Pre 5.3에 God awful GC가 있기 때문에 큰 일을하는 경우 메모리 문제가 발생할 수 있습니다.

해결책 2


스크립트를 종료하는 모든 작업자에게 종료 기능을 추가 할 수도 있습니다. 다시 시작하려면 Gearman에게 최우선 순위를두기 위해 간단히 전화를 걸어야합니다.

function AutoRestart() {
   static $startTime = time();

   if (filemtime(__FILE__) > $startTime) {
      exit();
   }
}

AutoRestart();  

흠, 당신은 소스 코드가 수정 된 경우 가끔 확인하기 위해 작업자에서 코드를 구현할 수 있습니다. 그렇다면 그렇다면 적합하면 스스로를 죽일 수 있습니다. 즉, 직장의 한가운데에 있고 직업이 매우 큰지 확인하십시오.

다른 방법으로는 네트워크를 통해 어떤 종류의 인터럽트를 구현하여 기회가있을 때마다 중지 할 수 있습니다.

마지막 솔루션은이 기능을 포함하도록 Gearman의 소스를 수정하는 데 도움이됩니다.

나는 최근에도 이것을 보고 있었습니다(Gearman::XS를 사용하는 Perl에서는).내 사용 사례는 귀하의 것과 동일했습니다. 오랫동안 근무하는 기어맨 작업자가 주기적으로 새 버전을 확인하고 다시 로드할 수 있도록 허용했습니다.

나의 첫 번째 시도는 작업자 스크립트 버전을 마지막으로 확인한 이후 얼마나 오랫동안 작업자가 추적하도록 하는 것이었습니다(md5sum도 작동함).그런 다음 N초가 경과하면 작업 사이에 새 버전이 사용 가능한지 확인하고 자체를 다시 시작합니다(fork()/exec()).이는 제대로 작동했지만 희귀 작업에 등록된 작업자는 잠재적으로 work()가 반환되어 현재 시간을 확인하기까지 몇 시간씩 기다려야 할 수 있습니다.

그래서 이제 work()를 사용하여 작업을 기다릴 때 상당히 짧은 시간 초과를 설정하여 시간을 더 정기적으로 확인할 수 있습니다.PHP 인터페이스에서는 작업 등록 시 이 시간 초과 값을 설정할 수 있다고 제안합니다.새 버전 확인을 실행하기 위해 SIGALRM을 사용하고 있습니다.Perl 인터페이스는 work()를 차단하므로 처음에는 경보가 트리거되지 않았습니다.시간 제한을 60초로 설정하면 SIGALRM이 작동합니다.

누군가가 Perl을 운영하는 작업자에 대한 답변을 찾고 있다면, 그것은 Gearmanx :: 스타터 도서관은 용입니다. 현재 작업을 완료 한 후 근로자를 중지 할 수 있습니다. 두 가지 다른 방법으로 외부 적으로 근로자 프로세스를 보내거나 전역 변수를 설정하여 프로그래밍 방식으로 전송합니다.

근로자가 PHP로 작성되었다는 사실을 감안할 때 알려진 일정에 따라 재활용하는 것이 좋습니다. 이것은 시작된 이래 정적 시간이 될 수 있거나 특정 수의 작업을 시도한 후에 수행 할 수 있습니다.

이것은 본질적으로 하나의 돌로 두 마리의 새를 죽입니다. 당신은 메모리 누출 가능성을 완화하고 있으며, 근로자가 잠재적으로 새로운 코드를 선택할 때를 결정할 수있는 일관된 방법이 있습니다.

나는 일반적으로 직원들에게 자신의 간격을 STDOUT 및/또는 로깅 시설에보고하여 작업자가 현재 위치를 확인하는 것이 간단합니다.

나는이 같은 문제를 해결하고 Python 2.7에 대한 해결책을 제시했습니다.

Gearman을 사용하여 시스템의 다른 구성 요소와 통신하는 Python 스크립트를 작성합니다. 스크립트에는 여러 작업자가 있으며 각 작업자가 별도의 스레드로 실행됩니다. 작업자는 모두 Gearman 데이터를 받고 해당 데이터를 메시지 대기열에 처리하고 저장하며 기본 스레드는 필요에 따라 큐의 데이터를 제거 할 수 있습니다.

각 작업자를 깨끗하게 폐쇄하는 내 솔루션은 서브 클래스였습니다. gearman.GearmanWorker 그리고 work() 기능:

from gearman import GearmanWorker
POLL_TIMEOUT_IN_SECONDS = 60.0
class StoppableWorker(GearmanWorker):
    def __init__(self, host_list=None):
        super(StoppableWorker,self).__init__(host_list=host_list)
        self._exit_runloop = False


    # OVERRIDDEN
    def work(self, poll_timeout=POLL_TIMEOUT_IN_SECONDS):
        worker_connections = []
        continue_working = True

        def continue_while_connections_alive(any_activity):
            return self.after_poll(any_activity)

        while continue_working and not self._exit_runloop:
            worker_connections = self.establish_worker_connections()
            continue_working = self.poll_connections_until_stopped(
                worker_connections,
                continue_while_connections_alive,
                timeout=poll_timeout)

        for current_connection in worker_connections:
            current_connection.close()

        self.shutdown()


    def stopwork(self):
        self._exit_runloop = True

Gearmanworker처럼 사용하십시오. 대본을 종료 할 때가되면 stopwork() 기능. 즉시 멈추지 않을 것입니다 poll_timeout 런 루프에서 시작하기 몇 초 전에.

몇 가지 현명한 방법이있을 수 있습니다 stopwork() 기능. 제 경우에는 기본 스레드에서 임시 Gearman 클라이언트를 만듭니다. 종료하려는 작업자의 경우 Gearman 서버를 통해 특수 정지 명령을 보냅니다. 근로자 가이 메시지를 받으면 스스로를 종료하는 것을 알고 있습니다.

도움이 되었기를 바랍니다!

http://phpscaling.com/2009/06/23/doing-the-work-elsewhere-sidebar-running-the-worker/

위의 기사에서 알 수 있듯이, 나는 Bash Shell 스크립트 내부에서 작업자를 실행하여 가끔 일자리를 정리하기 위해 종료하거나 작업자 스크립트를 다시로드하거나 주어진 작업이 제공되면 특정로 종료 할 수 있습니다. 코드를 종료하고 종료합니다.

이것은 지속적인 통합 시스템에 잘 맞습니다. 나는 당신이 그것을 가지고 있기를 바랍니다. 당신은 곧 그것을 가져야합니다 :-)

새 코드를 확인하면 서버에 자동으로 구축 및 배포됩니다. 빌드 스크립트의 일환으로 모든 노동자를 죽이고 새로운 직원을 시작합니다.

나는 둘 다 지원하는 다음 코드를 사용합니다 Ctrl-C 그리고 kill -TERM. 기본적으로 supervisor 보낸다 TERM 수정되지 않은 경우 신호 signal= 환경. PHP 5.3+에서 declare(ticks = 1) 더 이상 사용되지 않습니다 pcntl_signal_dispatch() 대신에.

$terminate = false;
pcntl_signal(SIGINT, function() use (&$terminate)
{
    $terminate = true;
});
pcntl_signal(SIGTERM, function() use (&$terminate)
{
    $terminate = true;
});

$worker = new GearmanWorker();
$worker->addOptions(GEARMAN_WORKER_NON_BLOCKING);
$worker->setTimeout(1000);
$worker->addServer('127.0.0.1', 4730);
$worker->addFunction('reverse', function(GearmanJob $job)
{
    return strrev($job->workload());
});

$count = 500 + rand(0, 100); // rand to prevent multple workers restart at same time
for($i = 0; $i < $count; $i++)
{
    if ( $terminate )
    {
        break;
    }
    else
    {
        pcntl_signal_dispatch();
    }

    $worker->work();

    if ( $terminate )
    {
        break;
    }
    else
    {
        pcntl_signal_dispatch();
    }

    if ( GEARMAN_SUCCESS == $worker->returnCode() )
    {
        continue;
    }

    if ( GEARMAN_IO_WAIT != $worker->returnCode() && GEARMAN_NO_JOBS != $worker->returnCode() )
    {
        $e = new ErrorException($worker->error(), $worker->returnCode());
        // log exception
        break;
    }

    $worker->wait();
}

$worker->unregisterAll();

내가하는 일은 사용하는 것입니다 gearmadmin 일자리가 실행되는지 확인하려면 admin API를 사용하여 UI를 만들었습니다. 일자리가 멍청하게 앉아있을 때, 그들을 죽이는 데 아무런 해가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top