2017-02-23 68 views
0

我有一個3 beanstalkd隊列進程運行在相同的ip但不同的端口上。我有一個單獨的服務器運行主管並行產生php工作(每個beanstalkd端口20)來處理隊列。我的問題是,似乎兩個進程可以在同一臺服務器上同時保留相同的作業ID。Pheanstalk保留相同的beanstalkd作業兩次或更多

下面是我的一些日誌輸出樣本:

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) 

似乎右後兩個相互儲量發生,第一個進程完成之前,第2貯存發生,刪除作業。

我在每個jobid的redis中添加了一個計數器,很明顯,當它保留第二次時,計數器上升一次(tr)。 TTRR設置爲3600,因此在第一個過程完成之前,它無法到期。

這是什麼工作狀態看起來像右邊的第二個過程後備用:

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', 
)) 

這種行爲是很隨意的,有時只有一個進程將能夠保留,直到作業鎖,有時2,有時甚至4個或更多(很少)。當然,這會造成執行次數不一致的重複作業。

短版本的代碼:

$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(); 

protected function _delete_job() 
{ 
    $this->pheanstalk->delete($this->job); 
    $this->log_message('info', __METHOD__ . ": DELETED JOB (" . $this->_logDetails() . ")"); 
} 
+0

請將您的代碼發佈到「預定」作業,發送給作品,然後在完成時刪除它。 –

+0

@AlisterBulman更新了一些代碼 – pierdevara

+0

只有一個Beanstalkd服務器時問題是否仍然存在?所有的服務器都有不同的二進制日誌等配置,爲什麼還要使用多個配置? –

回答

0

的問題是一個TCP連接的我的代碼process_job位之內發生的事情。 pheanstalk對象將被覆蓋在執行鏈的某個地方。

我有一個庫包裝pheanstalk在發送put命令之前檢查可用的最空的beanstalkd服務器。然後,它會創建一個具有最佳服務器細節的新Pheanstalk實例,並將其保存爲當前連接,然後調度該命令。

有時工作人員可以發送一個子作業到隊列中。該庫最初將加載到worker中以獲取作業,並再次在process_job中發送到隊列中。由於Codeigniter中的依賴注入,該庫會引用同一個對象,並且在process_job內部,它將覆蓋worker的當前連接並導致TCP斷開連接。

相關問題