tp5结合 beanstalkd,supervisor 的使用
最近在用消息队列,并结合网上一些文章,集成出一个精华版:
1.安装beanstalk
在linux
yum install -y beanstalkd
运行
nohup beanstalkd &
安装完后启动,若不启动运行phenstalk会报错

2.安装php消息队列包 phenstalk
在tp5项目中运行
composer require pda/pheanstalk
安装后,记得放行端口 11300
踩坑注意 : 如果使用过了一个 tube名 (这里是order) ,则下个消息队列要使用新的 tube 名字,因为开启了守护进程,建议不要重新用一个管道名写逻辑
class Index
{
public function index() //前台下单,类似生产者
{
$data = [
'name' => '消息队列1',
'good_id' => mt_rand(1000,9999),
];
$pda = Pheanstalk::create('127.0.0.1');
//投入到管道中 等待消费者消费 参数分别是 1 数据 2优先级 3设置延迟秒数处理
$id = $pda->useTube('order')->put(json_encode($data),0,3);
dump('生成管道'.$id->getId());
}
public function cost() //创建消费者消费任务数据
{
$pda = Pheanstalk::create('127.0.0.1');
// 获取管道并消费
$job = $pda->watch('order')->ignore('default')->reserve();// 获取任务数据
$data = $job->getData();
dump($data);
// 处理完任务后就删除掉
$pda->delete($job);
}
}
建议 用网页开两个页面测试,先运行index() 再运行cost()
3.安装supervisor
linux中运行
# yum install epel-release
# yum install supervisor
//设置成开机自动启动
# systemctl enable supervisord
自定义配置
1.在这里我创建了一个命名为supervisor的目录用于存放supervisor和队列的日志文件以及include的配置文件,其目录结构

创建supervisord的日志文件

然后找到/etc/supervisord.conf配置文件,修改一些路径
; 将supervisor.sock 的路径换成如下
[unix_http_server]
file=/var/supervisor/run/supervisor.sock ; (the path to the socket file)
; 将supervisord.log 和 supervisord.pid 的路径换成如下
[supervisord]
logfile=/var/supervisor/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/supervisor/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
; 将supervisor.sock 的路径换成如下
[supervisorctl]
serverurl=unix:///var/supervisor/run/supervisor.sock ; use a unix:// URL for a unix socket
; 将最底部的files路径换成如下
[include]
files = /var/supervisor/conf/*.conf
4.使用supervisor 配置守护进程
在/var/supervisor/conf目录里创建一个 selectMsg.conf ,内容如下:
[program:selectMsg] ;项目名称 自定义
directory = /www/wwwroot/tp5.1Project ; 项目路径
command = /usr/bin/php think xxxxx ; 这里是tp5 command的 启动命令 (php think 文件名 )
process_name=%(program_name)s_%(process_num)02d
numprocs = 1 ; 开启的进程数量
autostart = true ; 在 supervisord 启动的时候也自动启动
startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true ; 程序异常退出后自动重启
startretries = 3 ; 启动失败自动重试次数,默认是 3
user = root ; 用哪个用户启动
redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 50MB ; stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数
; stdout 日志文件,需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /var/supervisor/log/select_msg.log ;日志记录的位置
loglevel=info
在log创建上面配置的日志路径:名字由上面的 stdout_logfile 定义

同上操作,创建一个守护,守护 beanstalkd
创建 beanstalkd.conf
; 使用Pheanstalk队列 需要先运行beanstalkd,所以要把beanstalkd守护
[program:beanstalkds] ;项目名称
directory = /usr/bin ; 程序的启动目录,项目根目录的上一级
command = beanstalkd ; 启动命令
process_name=%(program_name)s_%(process_num)02d
numprocs = 1 ; 开启的进程数量 该进程只能开一个因为beanstalkd默认端口11300
autostart = true ; 在 supervisord 启动的时候也自动启动
startsecs = 5 ; 启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true ; 程序异常退出后自动重启
startretries = 3 ; 启动失败自动重试次数,默认是 3
user = root ; 用哪个用户启动
redirect_stderr = true ; 把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 50MB ; stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数
; stdout 日志文件,需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /var/supervisor/log/beanstalkd.log
loglevel=info
;对于单模块而言,不同的业务逻辑为了区分可能会存在多个队列名,这种情况将多个队列名用逗号拼接起来,如下
;command = php think queue:work --queue queueName1,queueName2 --daemon
对应的日志文件

重启配置
supervisorctl reload
或
systemctl restart supervisord
查看状态,RUNNING 或 starting 则成功,若是其他状态,则去 /var/supervisor/log/supervisor.log 查看报错
supervisorctl status
注意,每次修改守护的php 类的代码,都要重启supervisor
5. 使用tp5 的command
tp5中执行,也可以手动创建,注意 文件夹 application/command 和 方法 configure() execute 必须有
php think make:command Test
三处名字必须一样, 此处文件名就是上面 supervisor 配置的 /usr/bin/php think test

守护进程守护之后,只要写生产者 就可以随时被监听 消费了!
最后,记得设置数据库断开重连. database.php 中修改
'break_reconnect' => true,
使用实例: 监听频繁的数据库操作,生产者 放入到管道 消费者排队消费,防止高并发的db操作 带来数据库压力
消费者:
//设置php脚本执行时间
set_time_limit(0);
//设置socket连接超时时间
ini_set('default_socket_timeout', -1);
class addWorkAttend extends Command
{
protected function configure()
{
$this->setName('addWorkAttend');
}
protected function execute(Input $input, Output $output)
{
$pda = Pheanstalk::create('127.0.0.1');
// 获取管道并消费
while (1){
try {
$job = $pda->watch('records')->ignore('default')->reserveWithTimeout(60);
// 接受成功则 做数据库操作
if ($job != false && $job->getData()) {
$data = json_decode($job->getData(), true);
if ($this->records($data))
$pda->delete($job); // 插入Db操作
else
$pda->release($job); // 处理失败
}else
continue; // 跳出一次循环
} catch (\Exception $e) {
logs('消息队列错误,'.$e->getMessage(),'error');
die;
}
}
}
生产者:
public function setArrive($d) // 设置已到校
{
// $d 是要插入的数据
$pda = Pheanstalk::create('127.0.0.1');
//投入到管道中 等待消费者消费 参数分别是 1 数据 2优先级 3设置延迟秒数处理
$pda->useTube('records')->put(json_encode($d),0,3);
}
前端操作后执行生产接口就可以了
beanstalk常用方法:https://www.kancloud.cn/vson/php-message-queue/895571

浙公网安备 33010602011771号