J'ai 3 processus de file d'attente beanstalkd qui s'exécutent sur la même adresse IP mais sur des ports différents. J'ai un serveur séparé exécutant le superviseur spawning php travailleurs en parallèle (20 par port beanstalkd) pour traiter la file d'attente. Mon problème est qu'il semble que deux processus peuvent réserver le même ID de travail sur le même serveur en même temps.Pheanstalk réservant le même travail beanstalkd deux fois ou plus
Voici quelques exemple de sortie de mon journal:
2017-02-23 09:59:56 --> START JOB (port: 11301 | u: 0.45138600 1487861996 | jid:1695074 | pid:30019 | j:leads_to_tags_add | tr:1)
2017-02-23 09:59:57 --> START JOB (port: 11301 | u: 0.55024800 1487861997 | jid:1695074 | pid:30157 | j:leads_to_tags_add | tr:2)
2017-02-23 09:59:58 --> DEL JOB (port: 11301 | u: 0.54731000 1487861998 | jid:1695074 | pid:30019 | j:leads_to_tags_add)
2017-02-23 09:59:58 --> DEL JOB (port: 11301 | u: 0.58927900 1487861998 | jid:1695074 | pid:30157 | j:leads_to_tags_add)
Il semble que les deux réserves se trouvent juste après l'autre, et la deuxième réserve se produit avant la première fin du processus et supprime le travail.
J'ai ajouté un compteur en redis par jobid et il est clair qu'au moment où il réserve la deuxième fois, le compteur monte une fois (tr). Le TTRR est défini sur 3600, il n'y a donc aucun moyen qu'il expire avant la fin du premier processus.
C'est ce que l'état du travail ressemble juste après le second processus réserve:
Pheanstalk\Response\ArrayResponse::__set_state(array(
'id' => '1695074',
'tube' => 'action-medium',
'state' => 'reserved',
'pri' => '0',
'age' => '1',
'delay' => '0',
'ttr' => '3600',
'time-left' => '3599',
'file' => '385',
'reserves' => '2',
'timeouts' => '0',
'releases' => '0',
'buries' => '0',
'kicks' => '0',
))
Ce comportement est très aléatoire, parfois un seul processus sera en mesure de réserver jusqu'à ce que les serrures d'emploi, parfois 2, parfois même 4 ou plus (rarement). Bien sûr, cela crée un nombre incohérent de tâches en double en cours d'exécution.
Version courte du code:
$this->job = $this->pheanstalk->watch($tube)->reserve($timeout);
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
// error was suppressed with the @-operator
if (0 === error_reporting()) {
return false;
}
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
$this->log_message('info', __METHOD__ . ": START JOB (" . $this->_logDetails() . " | tr:{$tries})");
if ($this->_process_job()) {
$this->log_message('info', __METHOD__ . ": FINISHED JOB (" . $this->_logDetails() . ")");
$this->_delete_job();
} else {
$this->log_message('error', __METHOD__ . ": FAILED JOB (" . $this->_logDetails() . ")");
}
restore_error_handler();
et
protected function _delete_job()
{
$this->pheanstalk->delete($this->job);
$this->log_message('info', __METHOD__ . ": DELETED JOB (" . $this->_logDetails() . ")");
}
S'il vous plaît envoyer votre code où vous «réservez» le travail, envoyez-le à travailler sur, puis «supprimer» lorsqu'il est terminé. –
@AlisterBulman mis à jour avec du code – pierdevara
Les problèmes se produisent-ils toujours avec un seul serveur Beanstalkd? Est-ce que tous les serveurs ont des configs différentes pour la journalisation binaire etc., et pourquoi en utiliser plus d'une de toute façon? –