2014-11-10 16 views
8

Ho una semplice applicazione Web scritta con il framework Laravel 4.2. Ho configurato il componente della coda di Laravel per aggiungere nuovi elementi di coda a un server beastalkd localmente in esecuzione.Più ascoltatori di code eseguiranno lo stesso lavoro su più processi

In sostanza, esiste una route POST che aggiungerà un elemento alla provetta beanstalkd.

Ho quindi impostato il supervisore per eseguire artisan queue:listen come tre processi separati. Il problema che sto vedendo è che i diversi processi queue:listen finiranno per spawnare ovunque da uno a tre processi queue:worker per un solo lavoro inserito.

Il risultato finale è che un lavoro inserito nella coda viene talvolta elaborato da più lavoratori contemporaneamente, cosa che sto ovviamente cercando di evitare.

Il codice del lavoro è relativamente semplice:

<?php 

use App\Repositories\URLRepository; 

class ProcessDataJob { 
    private $urls; 

    public function __construct(URLRepository $urls) 
    { 
     $this->urls = $urls; 
    } 

    public function fire($job, $data) 
    { 
     $input = $data['post']; 

     if (!isset($data['post']) && !is_array($data['post'])) { 
      Log::error('[Job #'.$job->getJobId().'] $input was empty inside CreateAuditJob. Deleting job. Quitting. Bye!'); 
      $job->delete(); 
      return false; 
     } 

     // 
     // ... code that will take a few hours to run. 
     // 

     $job->delete(); 
     Log::info('[Job #'.$job->getJobId().'] ProcessDataJob was successful, deleting the job!'); 
     return true; 
    } 
} 

La parte divertente è che la maggior parte del (duplicato) coda di lavoratori non riescono quando si elimina il lavoro con questa sinistra nel log degli errori:

exception 'Pheanstalk_Exception_ServerException' with message 'Job 3248 NOT_FOUND: does not exist or is not reserved by client' 

Il ttr (Time to Run) è impostato su 172.800 secondi (o 48 ore), che è molto più grande del tempo necessario per il completamento del lavoro.

risposta

3

qual è il lavoro time_to_run in coda? Se l'esecuzione del processo richiede più tempo di time_to_run secondi, il lavoro viene automaticamente reinserito in coda e diventa idoneo per essere eseguito dal lavoratore successivo.

Un lavoro prenotato ha time_to_run secondi per essere cancellato, rilasciato o toccato. Chiamando touch() si riavvia il timer di timeout, in modo che i lavoratori possano utilizzarlo per avere più tempo per terminare. O utilizzare un valore abbastanza grande durante l'accodamento.

Ho trovato il documento protocollo beanstalkd utili https://github.com/kr/beanstalkd/blob/master/doc/protocol.md

+0

ok, tanto per la soluzione facile. I registri mostrano che i processi dupliati iniziano tutti nello stesso momento? O sono sfalsati? È possibile che ci sia qualche timeout nell'app da qualche parte. Altrimenti potresti dover scavare nel codice di spedizione per rintracciare ciò che sta facendo. Ho scritto sistemi di code (due in php, un terzo con beanstalk), ma non conosco laravel. – Andras

+0

I lavori duplicati iniziano __usualmente__ entro 10 secondi l'uno dall'altro. Non sembra esserci un timeout all'interno dell'app, specialmente con la connessione beanstalk. Non vengono lanciate eccezioni o errori. Sto pensando che potrebbe essere un bug del beanstalk. – timgws

+0

10 secondi è un tempo lungo ... che strano. Puoi strumentare la spedizione? solo per registrare l'ID del lavoro restituito da beanstalk reserve()? Ricerca di bisezione, o restringila a beanstalk o all'app. Per il timeout, stavo pensando a un "errore di dichiarazione decimale dopo 10 minuti" di tipo di cosa a tempo di esecuzione massimo configurato – Andras

2

Dal momento che si esegue con laravel, verificare il file di configurazione queue.php.

Modificare il valore ttr da 60 (predefinito) a qualcos'altro che è meglio per voi.

'beanstalkd' => array(
     'driver' => 'beanstalkd', 
     'host' => 'localhost', 
     'queue' => 'default', 
     'ttr' => 600, //Example 
    ), 
Problemi correlati