目前來(lái)看Webman程序運(yùn)行期間一切是正常的,只是當(dāng)我把服務(wù)停止時(shí),會(huì)報(bào)出很多下面這樣的報(bào)錯(cuò):
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
webman版本是最新的,workerman版本是最新的,操作系統(tǒng)是centos7.9,php版本7.4.30,event版本也是目前最新的3.0.8
因?yàn)楫?dāng)我試著把所有消費(fèi)監(jiān)聽(tīng)進(jìn)程都關(guān)掉后,無(wú)論怎樣開(kāi)啟服務(wù)、停止服務(wù)、重啟服務(wù)、重載服務(wù),怎么搞都不會(huì)發(fā)生Epoll報(bào)錯(cuò)。
簡(jiǎn)單說(shuō)一下我的操作:
class Rabbitmq
{
/**
* 發(fā)布消息到worker隊(duì)列,支持一次性發(fā)布多個(gè)消息
*
* @author Aaron <chenqiang@h024.cn>
*
* @param string|array $msgData 需要入隊(duì)的消息,單一消息為字符串類(lèi)型,多個(gè)消息是數(shù)組類(lèi)型
* @param string $queueName 隊(duì)列名稱(chēng),默認(rèn)空串就是默認(rèn)隊(duì)列
* @param \PhpAmqpLib\Channel\AMQPChannel $channel 指定rabbit通道,默認(rèn)null表示使用默認(rèn)通道
*/
public static function publishWorkerQueue($msgData, string $queueName = '', \PhpAmqpLib\Channel\AMQPChannel $channel = null)
{
// $log = \support\Log::channel('producer');
if ($queueName == '') {
$queueName = env('RABBITMQ_DEFAULT_QUEUE', 'default');
}
if (is_null($channel)) {
$channel = \app\bootstrap\Rabbitmq::$defaultProducerChannel;
}
$channel->queue_declare($queueName, false, true, false, false);
if (!is_array($msgData)) {
$msgData = array($msgData);
}
// 遍歷數(shù)組,對(duì)每一個(gè)元素做入隊(duì)操作
foreach ($msgData as $dataBody) {
// 把字符串類(lèi)型的元素入隊(duì),忽略其他類(lèi)型的元素
try {
$dataBody = (string)$dataBody;
} catch (\Exception $e) {
$dataBody = json_encode($dataBody);
}
$msg = new AMQPMessage(
$dataBody,
array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
);
// $log->debug("{$queueName}入隊(duì)數(shù)據(jù): {$dataBody}");
$channel->basic_publish($msg, '', $queueName);
}
}
/**
* 用workerman的rabbitmq組件實(shí)現(xiàn)的異步消息發(fā)布
*
* @author Aaron <chenqiang@h024.cn>
*
* @param array $option // 連接客戶(hù)端的配置
* @param string $queue // 指定隊(duì)列名
* @param string $message // 要發(fā)布的消息
*/
public static function asyncPublishWorkerQueue(array $option, string $queue, string $message)
{
(new \Workerman\RabbitMQ\Client($option))->connect()->then(function (\Workerman\RabbitMQ\Client $client) use ($message) {
return $client->channel();
})->then(function (\Bunny\Channel $channel) use ($message, $queue) {
return $channel->queueDeclare($queue, false, true, false, false)->then(function () use ($channel) {
return $channel;
});
})->then(function (\Bunny\Channel $channel) use ($message, $queue) {
$briefMsg = mb_substr($message, 0, 50);
// \support\Log::channel('producer')->debug(" [x] Sending {$briefMsg} to {$queue}\n");
return $channel->publish($message, [], '', $queue)->then(function () use ($channel) {
return $channel;
});
})->then(function (\Bunny\Channel $channel) use ($message, $queue) {
$briefMsg = mb_substr($message, 0, 50);
// \support\Log::channel('producer')->debug(" [x] Sent {$briefMsg} to {$queue}\n");
$client = $channel->getClient();
// return $client;
return $channel->close()->then(function () use ($client) {
return $client;
});
// });
})->then(function (\Workerman\RabbitMQ\Client $client) {
$client->disconnect();
});
}
/**
* 通過(guò)workerman的rqbbitmq組件實(shí)現(xiàn)的異步隊(duì)列消費(fèi),需要執(zhí)行$channel->ack方法以完成消費(fèi)
*
* @author Aaron <chenqiang@h024.cn>
*
* @param array $option // 連接客戶(hù)端的配置
* @param string $queue
* @param callable $callback // 消費(fèi)的具體回調(diào)方法,接收參數(shù)\Bunny\Message $message, \Bunny\Channel $channel, \Workerman\RabbitMQ\Client $client
*/
public static function asyncConsumeWorkerQueue(array $option, string $queue, callable $callback, bool $noAck = MQ_NO_AUTO_ACK)
{
(new \Workerman\RabbitMQ\Client($option))->connect()->then(function (\Workerman\RabbitMQ\Client $client) {
return $client->channel();
})->then(function (\Bunny\Channel $channel) use ($queue) {
return $channel->queueDeclare(
$queue,
false,
true,
false,
false
)->then(function () use ($channel) {
return $channel;
});
})->then(function (\Bunny\Channel $channel) {
return $channel->qos(0, 1, false)->then(function () use ($channel) {
return $channel;
});
})->then(function (\Bunny\Channel $channel) use ($callback, $queue, $noAck) {
echo " [*] Waiting for messages on {$queue}.\n";
// noAck = false表示需要消費(fèi)進(jìn)程手動(dòng)判斷
$channel->consume(
$callback,
$queue,
'',
false,
$noAck
);
});
}
}
class TestConsumer
{
public function onWorkerStart(Worker $worker)
{
// 回調(diào)函數(shù)就是具體的隊(duì)列消費(fèi)者程序
$callback = array($this, 'asyncConsume');
// 用異步rabbitmq組件來(lái)監(jiān)聽(tīng)隊(duì)列并完成消費(fèi),不會(huì)造成worker阻塞
\util\Rabbitmq::asyncConsumeWorkerQueue(
\app\bootstrap\Rabbitmq::$asyncConsumerOption,
QUEUENAME_TEST,
$callback
);
}
/**
* 異步消費(fèi)回調(diào)函數(shù)
*
* @author Aaron <chenqiang@h024.cn>
*
* @param \Bunny\Message $message 異步消息體
* @param \Bunny\Channel $channel 異步隊(duì)列通道
* @param \Workerman\RabbitMQ\Client $client 異步隊(duì)列客戶(hù)端
*/
public function asyncConsume(Message $message, Channel $channel, Client $client)
{
\support\Log::channel('consumer')->debug("test消費(fèi)者: 收到消息 " . $message->content);
$data = json_decode($message->content, true);
/// ... 具體消費(fèi)動(dòng)作 ...
$channel->ack($message);
\support\Log::channel('consumer')->debug("test消費(fèi)者: 消費(fèi)完畢 " . $message->content);
}
}
Epoll數(shù)量與rabbitmq隊(duì)列消費(fèi)進(jìn)程數(shù)量正相關(guān)
# php start.php start
Workerman[start.php] start in DEBUG mode
-------------------------------------------------- WORKERMAN --------------------------------------------------
Workerman version:4.0.33 PHP version:7.4.30
--------------------------------------------------- WORKERS ---------------------------------------------------
proto user worker listen processes status
tcp root data_worker http://0.0.0.0:9607 8 [OK]
tcp root esl_listener none 1 [OK]
tcp root async_task_proxy websocket://0.0.0.0:9608 1 [OK]
tcp root task_init text://0.0.0.0:9611 4 [OK]
tcp root task_start text://0.0.0.0:9612 4 [OK]
tcp root task_call_consumer none 4 [OK]
tcp root task_data_update_consumer none 4 [OK]
tcp root task_billing_consumer none 8 [OK]
---------------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
[*] Waiting for messages on task_data_update.
[*] Waiting for messages on task_data_update.
[*] Waiting for messages on task_call.
[*] Waiting for messages on task_data_update.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_data_update.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_call.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_billing.
[*] Waiting for messages on task_call.
[*] Waiting for messages on task_call.
^CPHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Workerman[start.php] stopping ...
PHP Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 8 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 8 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(1) on fd 6 failed. Old events were 6; read change was 0 (none); write change was 2 (del): Bad file descriptor in Unknown on line 0
PHP Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Warning: Unknown: Epoll MOD(4) on fd 6 failed. Old events were 6; read change was 2 (del); write change was 0 (none): Bad file descriptor in Unknown on line 0
Workerman[start.php] has been stopped
rabbitmq client用單例,一個(gè)進(jìn)程保持一個(gè)連接,你的epoll在fd 6上面失敗了,失敗原因就是讀取不到描述文件了,一般情況就是你的loop覆蓋了;
每個(gè)rabbitmq client會(huì)復(fù)用當(dāng)前進(jìn)程的globalEvent,如果使用new的話(huà),每次的client對(duì)象都不是同一個(gè);
除了上述問(wèn)題的可能性外,還有一種:當(dāng)你的消費(fèi)進(jìn)程啟動(dòng)后,client的消費(fèi)是異步的,也就是你在這一個(gè)loop內(nèi)進(jìn)行stop的話(huà),你的消費(fèi)可能還正在消費(fèi)中,相當(dāng)于在循環(huán)中中止該消費(fèi)loop,可能因?yàn)橐恍┮馔馇闆r不能等待消費(fèi)完畢后中止,而是直接中斷;
當(dāng)然具體的還是得具體代碼來(lái)分析;
推薦webman環(huán)境下可以直接使用rabbitmq客戶(hù)端插件,是生產(chǎn)可用的,可以放心使用;
http://wtbis.cn/plugin/67