<?php
namespace app\index\controller;
use think\Cache;
use think\Controller;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use think\App;
use think\Db;
class Rabbitmq extends Controller
{
protected $redis_client;
public function __construct(App $app = null)
{
$this->redis_client = new \Redis();
$this->redis_client->connect('127.0.0.1',6379);
}
/**
* @throws \Exception
* 生产消息
*/
public function product(){
$conf = [
'host' => '127.0.0.1',
'port' => 5672,
'user' => 'guest',
'pwd' => 'guest',
'vhost' => '/',
];
$exchangeName = 'order_test'; //交换机名----指定交换机名称
$queueName = 'order_list'; //队列名称---指定队列名称
$routingKey = 'order'; //路由关键字(也可以省略)--指定队列组---用于队列和交换机绑定
$conn = new AMQPStreamConnection( //建立生产者与mq之间的连接
$conf['host'], $conf['port'], $conf['user'], $conf['pwd'], $conf['vhost']
);
//建立通道
$channel = $conn->channel(); //在已连接基础上建立生产者与mq之间的通道
//开启发布确认模式
$channel->confirm_select();
//队列消息持久化;第二个参设置为true表示持久化
//$channel->queue_declare($queueName,true, false, false, null);
//初始化交换机,设置type,即推送类型 direct表示精准推送;fanout 表示广播,推送到绑定到此交换机下的所有队列;topic表示组播,比如上面我绑定的关键字是sms_send,那么他可以推送到*.sms_send的所有队列;
//参数说明:
//$channel->exchange_declare(交换机名称, 推送类型, 是否检测同名队列, 是否开启队列持久化, 通道关闭后是否删除队列);
$channel->exchange_declare($exchangeName, 'direct', false, true, false);
//初始化队列
//陈述说明:
//$channel->queue_declare(队列名称, 是否检测同名队列, 是否开启队列持久化, 队列是否可以被其他队列访问, 通道关闭后是否删除队列);
$channel->queue_declare($queueName, false, true, false, false); //声明初始化一条队列
//将队列与交换机进行绑定
$channel->queue_bind($queueName, $exchangeName, $routingKey); //将队列与某个交换机进行绑定,并使用路由关键字
$msg_arr=array(
"order"=>'003',
"age"=> '18',
"sex"=>'女',
"mobile"=>'13000000000',
"job_number"=>'test',
"sign"=>'003'
);
//消息内容
$msgBody = json_encode($msg_arr,JSON_UNESCAPED_UNICODE);
dump($msgBody);
//生成mq能看懂的消息
$msg=new AMQPMessage($msgBody);
//消息发送到指定交换机,指定路由关键词
$channel->basic_publish($msg,$exchangeName,$routingKey);
//推送成功
$channel->set_ack_handler(
function (AMQPMessage $message) {
echo "发送成功: ";
}
);
//推送失败
$channel->set_nack_handler(
function (AMQPMessage $message) {
echo "发送失败: ";
die;
}
);
$channel->wait_for_pending_acks();
$channel->close();
$conn->close();
}
/**
* @throws \ErrorException
* 消费消息
*/
public function consumer(){
$conf = [
'host' => '127.0.0.1',
'port' => 5672,
'user' => 'guest',
'pwd' => 'guest',
'vhost' => '/',
];
$exchangeName = 'order_test'; //交换机名----指定交换机名称
$queueName = 'order_list'; //队列名称---指定队列名称
$routingKey = 'order'; //路由关键字(也可以省略)--指定队列组---用于队列和交换机绑定
$conn = new AMQPStreamConnection( //建立生产者与mq之间的连接
$conf['host'], $conf['port'], $conf['user'], $conf['pwd'], $conf['vhost']
);
//建立通道
$channel = $conn->channel(); //在已连接基础上建立生产者与mq之间的通道
//初始化交换机,设置type,即推送类型 direct表示精准推送;fanout 表示广播,推送到绑定到此交换机下的所有队列;topic表示组播,比如上面我绑定的关键字是sms_send,那么他可以推送到*.sms_send的所有队列;
//参数说明:
//$channel->exchange_declare(交换机名称, 推送类型, 是否检测同名队列, 是否开启队列持久化, 通道关闭后是否删除队列);
$channel->exchange_declare($exchangeName, 'direct', false, true, false);
//初始化队列
//陈述说明:
//$channel->queue_declare(队列名称, 是否检测同名队列, 是否开启队列持久化, 队列是否可以被其他队列访问, 通道关闭后是否删除队列);
$channel->queue_declare($queueName, false, true, false, false); //声明初始化一条队列
//将队列与交换机进行绑定
$channel->queue_bind($queueName, $exchangeName, $routingKey); //将队列与某个交换机进行绑定,并使用路由关键字
echo "等待消息产生.....";
$callback = function($msg) {
dump("(1)接收到了消息...");
dump($msg->body);
//----------------以下-----利用redis分布式锁,对重读消息进行过滤-----------------------
$body_arr=json_decode($msg->body,JSON_UNESCAPED_UNICODE);
dump($body_arr);
$sign_exits = $this->redis_client->get($body_arr['sign']);
if(!empty($sign_exits)){
//已经消费过,不能重读消费
echo "消息已经被消费,被过滤掉了";
}else{
//利用redis分布式锁,避免重复消费
$this->redis_client->set($body_arr['sign'],"yijing_xiaofei",120);
echo "往下执行消费此消息..";
///-----你的逻辑处理-----
$body_arr['content']="消费了此消息";
$body_arr_json=json_encode($body_arr,JSON_UNESCAPED_UNICODE);
Db::table("sys_rabbit_mq")->insert(array("content"=>$body_arr_json,"create_time"=>date("Y-m-d H:i:s")));
}
//----------------以上-----利用redis分布式锁,对重读消息进行过滤-----------------------
};
/**
* RabbitMQ服务器在短时间内发送大量的消息给Consumer,如果你没有来得及Ack的话,那么服务端会积压大量的UnAcked消息,而Consumer如果来不急处理也会处于假死或程序崩溃。
*/
$channel->basic_consume($queueName, '', false, true, false, false, $callback);
while(count($channel->callbacks)) {
//sleep(1);
$channel->wait();
}
$channel->close();
$conn->close();
}
}
PHP RabbitMQ简单使用
最新推荐文章于 2024-05-17 15:13:18 发布