1. 找到配置文件,/etc/supervisor/supervisor.conf
添加
[include]
files = /www/server/panel/plugin/supervisor/profile/*.ini
test.ini文件内容
[program:rabbitmq-consume]
process_name=%(program_name)s_%(process_num)02d
directory=/www/wwwroot
command=/www/server/php/73/bin/php /www/wwwroot/project/yii swoole-consume/run
autostart=true
autorestart=true
user=www
numprocs=1
redirect_stderr=true
stdout_logfile=/www/wwwlogs/project_rabbitmq_consume.log
[program:swoole-crontab-server]
process_name=%(program_name)s_%(process_num)02d
directory=/www/wwwroot
command=/www/server/php/73/bin/php /www/wwwroot/project/yii swoole-crontab/server-run
autostart=true
autorestart=true
user=www
numprocs=1
redirect_stderr=true
stdout_logfile=/www/wwwlogs/project_swoole_crontab.log
[program:swoole-crontab-client]
process_name=%(program_name)s_%(process_num)02d
directory=/www/wwwroot
command=/www/server/php/73/bin/php /www/wwwroot/project/yii swoole-crontab/client-run
autostart=true
autorestart=true
user=www
numprocs=2
redirect_stderr=true
stdout_logfile=/www/wwwlogs/project_swoole_crontab.log
swoole-consume/run.php
<?php
/**
* 进程池多消费者,多队列消费rabbitMQ队列
*/
namespace console\controllers;
use common\enums\RabbitMqEnum;
use console\controllers\swoole_server\BaseSwooleServer;
use Exception;
use PhpAmqpLib\Exchange\AMQPExchangeType;
use ReflectionMethod;
use Swoole\Process\Pool;
use Yii;
/**
* rabbitMQ队列消费者进程池
*/
class SwooleConsumeController extends BaseSwooleServer
{
public $worker_num;
public $consume_setting = [
];
// 进程与消费者的对应关系
public $worker_queue_relate = [];
public function init(){
$worker_num_arr = array_column($this->consume_setting,'worker_num');
$this->worker_num = array_sum($worker_num_arr);
$worker_id = 0;
foreach($this->consume_setting as $key=>$queue_info){
$wait_assign_worker_num = $queue_info['worker_num'];
while($wait_assign_worker_num > 0){
$this->worker_queue_relate[$worker_id] = $key;
$worker_id ++;
$wait_assign_worker_num --;
}
}
}
/**
* 启动消费者
* @return void
*/
public function actionRun(){
// 计数器,当进程反复退出重启时,可能代码有致命错误,需要处理
// $atomic = new Atomic();
$pool = new Pool($this->worker_num);
//绑定一个事件
$pool->on("WorkerStart", function ($pool, $worker_id) {
echo 'worker_id:'.$worker_id.PHP_EOL;
$queue_key = $this->worker_queue_relate[$worker_id];
$queue_info = $this->consume_setting[$queue_key];
//设置进程名称
swoole_set_process_name('swoole : rabbitmq_process '.$queue_info['queue_name'].'_'.$worker_id);
$process = $pool->getProcess($worker_id);
try {
Yii::$app->services->rabbitMq->listen($queue_info['exchange'], $queue_info['queue_name'], function ($message) {
$res = $this->handleMessage($message);
Yii::getLogger()->flush(true);
return $res;
});
} catch (Exception $e) {
Yii::getLogger()->flush(true);
echo 'exception:' . $e->getMessage().$e->getFile().':'.$e->getLine().PHP_EOL;
}
});
//子进程关闭
$pool->on("WorkerStop", function ($pool, $workerId) {
echo "Worker#{$workerId} is stopped\n";
});
$pool->start();
}
/**
* 消息处理
* @param AMQPMessage $message
* @throws
* @return bool
*/
private function handleMessage($message)
{
$date = date('Y-m-d H:i:s');
$routing_key = $message->getRoutingKey();
$flush = '['.$date.']'.'队列(' . $routing_key . ')接收到消息,其内容为:' . $message->getBody();
$message_body = json_decode($message->getBody(), true);
$class = $message_body['handler_class'];
$method = $message_body['method'];
$data = $message_body['data'];
$data['message_id'] = $message->get('message_id');
if (!method_exists($class, $method)) {
//方法不存在,忽略
Yii::error('actionTaskConsume: class' . $class . ' ,method:' . $method . ' ,not exist');
return false;
}
$reflect_method = new ReflectionMethod($class, $method);
Yii::$app->db->close();
Yii::$app->redis->close();
$time1 = time();
if ($reflect_method->isStatic()) {
$res = $class::$method($data);
if ($res === false) Yii::error($class::$static_error ?? '未定义错误');
//if($res === false) throw new Exception($class::$static_error ?? '未定义错误');
} else {
$obj = new $class();
$res = $obj->$method($data);
if ($res === false) Yii::error($obj->error ?? '未定义错误');
//if($res === false) throw new Exception($obj->error ?? '未定义错误');
}
$time2 = time();
$total_time = $time2 - $time1;
if ($total_time > 1) $flush .= ',队列耗时:' .$total_time . '秒';
echo $flush . PHP_EOL . PHP_EOL;
return $res;
}
/**
* 重启消费者
* @return void
*/
public function actionRestartConsume(){
}
}