RabbitMQ+PHP
目录
介绍:RabbitMQ 是一个消息代理:它接受和转发消息。您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定邮递员最终会将邮件递送给您的收件人。在这个类比中,RabbitMQ 是一个邮箱、一个邮局和一个邮递员。
官网地址:https://www.rabbitmq.com/
一、 安装 RabbitMQ
服务端
- Docker 安装
# 拉取镜像:选择带有 management(包含web管理界面)
docker pull rabbitmq:management
# 查看所有镜像
docker images
# 创建镜像并启动容器
docker run -di --name MyRabbitMQ -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 5672:5672 -p 15672:15672 -p 25672:25672 -p 61613:61613 -p 1883:1883 rabbitmq:management
- Centos 安装
# 安装 socat
yum -y install socat
# 下载 erlang
wget http://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpm
# 安装erlang
rpm -ivh erlang-19.0.4-1.el7.centos.x86_64.rpm
# 下载 RabbitMQ
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/rabbitmq-server-3.6.10-1.el7.noarch.rpm
# 安装 RabbitMQ
rpm -ivh rabbitmq-server-3.6.10-1.el7.noarch.rpm
如果 centos 开启了防火墙,则需要开启端口:
# 查看端口是否开启;如果为 no,则执行第二条命令开启端口。
$ firewall-cmd --query-port=15672/tcp
$ firewall-cmd --zone=public --add-port=15672/tcp --permanent
# 开启后要重启防火墙。
$ systemctl restart firewalld.service
管理 UI 和 外部监控插件 rabbitmq_management
# 首先创建目录,否则可能报错:
mkdir /etc/rabbitmq
# 然后启用插件:
rabbitmq-plugins enable rabbitmq_management
- Ubuntu 20.04 安装
sudo apt-get install erlang-nox -y
sudo apt-get update
sudo apt-get install rabbitmq-server -y
# 添加用户
sudo rabbitmqctl add_user admin admin
# 赋予权限
sudo rabbitmqctl set_user_tags admin administrator
# 赋予 virtual host 中所有资源的配置、写、读权限
sudo rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'
管理命令
# 启动 rabbitmq 服务
service rabbitmq-server start
# 关闭 rabbitmq 服务
service rabbitmq-server stop
# 重启 rabbitmq 服务
service rabbitmq-server restart
# 查看 rabbitmq 状态
service rabbitmq-server status
管理 UI 和 外部监控插件 rabbitmq_management
# 启用 rabbitmq_manager
cd /etc/rabbitmq
sudo rabbitmq-plugins enable rabbitmq_management
账户:admin
密码:admin
二、 PHP RabbitMQ 客户端(示例:TP5)官方示例地址
Composer 安装
composer require php-amqplib/php-amqplib
添加配置信息 extra\rabbitmq.php
<?php
return [
'MQ' => [
'host' => '127.0.0.1',
'port'=>'5672',
'login'=>'admin',
'password'=>'admin',
'vhost'=>'/'
],
'sms_queue' => [
'exchange_name' => 'sms_exchange',
'exchange_type'=>'direct',
'queue_name' => 'sms_queue',
'route_key' => 'sms_roteking',
'consumer_tag' => 'consumer'
]
];
生产者 send.php
<?php
namespace app\hive\controller;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class Send extends Base
{
public static function pushMessage($data = "['code' => 1, 'msg' => 'success', 'ts' => time()]")
{
$config = config('rabbitmq.MQ');
$queueConfig = config('rabbitmq.sms_queue');
$connection = new AMQPStreamConnection( $config['host'], $config['port'], $config['login'], $config['password'], $config['vhost'] );
$channel = $connection->channel();
/*
name: $queue 声明队列
passive: false
持久durable: true 队列将在服务器重启后继续存在
互斥exclusive: false 队列可以通过其他渠道访问
auto_delete: false 通道关闭后,队列不会被删除
*/
$channel->queue_declare($queueConfig['queue_name'], false, true, false, false);
/*
name: $exchange 声明交换机
type: direct 直连方式
passive: false
durable: true 持久 交换器将在服务器重启后继续存在
auto_delete: false 一旦通道关闭,交换器将不会被删除。
*/
$channel->exchange_declare($queueConfig['exchange_name'], 'direct', false, true, false);
/*
$messageBody:消息体
content_type:消息的类型 可以不指定
delivery_mode:消息持久化最关键的参数
AMQPMessage::DELIVERY_MODE_NON_PERSISTENT = 1;
AMQPMessage::DELIVERY_MODE_PERSISTENT = 2;
*/
$messageBody = $data;
$message = new AMQPMessage($messageBody, array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
$channel->basic_publish($message, $queueConfig['exchange_name'],$queueConfig['route_key']);
$channel->close();
$connection->close();
echo " [x] Sent 'Hello World!'\n";
}
}
消费者 receive.php
<?php
namespace app\hive\controller;
use PhpAmqpLib\Connection\AMQPStreamConnection;
class Receive
{
public function start()
{
$config = config('rabbitmq.MQ');
$amqpDetail = config('rabbitmq.sms_queue');
$connection = new AMQPStreamConnection( $config['host'], $config['port'], $config['login'], $config['password'], $config['vhost'] );
$channel = $connection->channel();
$channel->queue_declare($amqpDetail['queue_name'], false, true, false, false);
$channel->exchange_declare($amqpDetail['exchange_name'], 'direct', false, true, false);
$channel->queue_bind($amqpDetail['queue_name'], $amqpDetail['exchange_name'],$amqpDetail['route_key']);
/*
queue: 从哪里获取消息的队列
consumer_tag: 消费者标识符
no_local: 不接收此使用者发布的消息
no_ack: 如果求设置为true,则此使用者将使用自动确认模式。详情请参见.
exclusive:请独占使用者访问,这意味着只有这个使用者可以访问队列
nowait:
callback: :PHP回调 array($this, 'process_message') 调用本对象的process_message方法
*/
$channel->basic_consume($amqpDetail['queue_name'], $amqpDetail['consumer_tag'], false, false, false, false, array($this, 'process_message'));
register_shutdown_function(array($this, 'shutdown'), $channel, $connection);
while (count($channel->callbacks)) {
$channel->wait();
}
}
function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
function process_message($message)
{
echo json_encode($message);
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
}
创建命令
<?php
namespace app\v1\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\hive\controller\Receive;
class Consumer extends Command
{
protected function configure()
{
$this->setName('consumer') ->setDescription('the consumer command');
}
protected function execute(Input $input, Output $output)
{
$consumer = new Receive();
$consumer->start();
}
}
在 app\command.php
声明
<?php
return [
'app\v1\command\Consumer',
];
常用命令
# 查看可以用的操作命令
php think
# 启动消费者
php think consumer
守护进程运行
# nohup表示不挂断地运行命令,&表示在后台运行,两个结合起来使用就可以守护进程运行
nohup php think consumer &
# 如果想关掉,可以先找到这个进程的id,然后杀掉这个进程
# 先找到进程id
ps -ef |grep mailer
# 然后杀掉进程
kill -9 进程id
如有问题请及时反馈。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析