rabbitmq工作模式(死信队列)
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
use PhpAmqpLib\Wire\AMQPTable;
class mq{
private static $obj = null;
private $conf=[];
private $connection=null;
private $channel=null;
/**
* 封闭构造
*/
private function __construct(){
//加载配置文件
$this->conf=[
'host'=>'192.168.202.138',
'port'=>5672,
'user'=>'myuser',
'pass'=>'mypass',
'exchange'=>'work',
'queue'=>'work',
'dlx_time'=>10000,
'dlx_max_len'=>5,
'exchange_dlx'=>'exchange.dlx',
'queue_dlx'=>'queue.dlx',
'routing_dlx'=>'routingkey'
];
}
/**
* 单例获取
*/
public static function getInstance(){
if(is_null(self::$obj)){
self::$obj = new mq();
}
return self::$obj;
}
//建立管道
public function channel(){
$this->connection = new AMQPStreamConnection($this->conf['host'],$this->conf['port'],$this->conf['user'],$this->conf['pass']);
$this->channel = $this->connection->channel();
}
public function Table(){
$args = new AMQPTable();
$args->set('x-message-ttl',$this->conf['dlx_time']);//消息过期方式:设置 $exchange 队列中的消息10s之后过期
$args->set('x-max-length',$this->conf['dlx_max_len']);//设置队列最大长度方式: x-max-length
$args->set('x-dead-letter-exchange', $this->conf['exchange_dlx']);//延迟结束后指向交换机(死信收容交换机)
$args->set('x-dead-letter-routing-key',$this->conf['routing_dlx']);//延迟结束后指向队列(死信收容队列),可直接设置queue name也可以
return $args;
}
//建立死信队列
public function dlx_queue(){
$this->channel();
$this->channel->exchange_declare($this->conf['exchange_dlx'], AMQPExchangeType::DIRECT, false, true);
$this->channel->exchange_declare($this->conf['exchange'], AMQPExchangeType::FANOUT, false, true);
$args = $this->Table();
$this->channel->queue_declare($this->conf['queue'], false, true, false, false, false, $args);
$this->channel->queue_declare($this->conf['queue_dlx'], false, true, false, false);
$this->channel->queue_bind($this->conf['queue'],$this->conf['exchange']); //队列绑定交换器
$this->channel->queue_bind($this->conf['queue_dlx'], $this->conf['exchange_dlx'],$this->conf['routing_dlx']);
}
//建立普通队列
public function queue(){
$this->channel->exchange_declare($this->conf['exchange'], AMQPExchangeType::DIRECT, false, false, false); // 试探性声明一个交换机
$this->channel->queue_declare($this->conf['queue'], false, false, false, false); // 试探性声明一个队列
}
public function message($body){
//DELIVERY_MODE_PERSISTENT消息持久化,重启rabbitmq,消息不会丢失
$message = new AMQPMessage($body,['content_type' =>'text/plain','delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
return $message;
}
public function channel_close(){
$this->channel->close(); // 关闭通道
}
public function connection_close(){
$this->connection->close(); // 关闭连接
}
public function dlx_send($body){
try {
$this->dlx_queue();
//开启消息确认//选择为 confirm 模式(此模式不可以和事务模式 兼容)
$this->channel->confirm_select();
//设置异步回调消息确认 (生产者 防止信息丢失)
$this->channel->set_ack_handler(function (AMQPMessage $message){
//echo 'ack' . $message->getBody();
});
//消息失败后处理方式
$this->channel->set_nack_handler(function (AMQPMessage $message){
//echo 'nack' . $message->getBody();
});
//$num=count($body);
//for ($i = 0; $i <$num; $i++) {
$message =$this->message($body);
$this->channel->basic_publish($message,$this->conf['exchange'],$this->conf['routing_dlx']);
//}
//$message =$this->message($body);
//$this->channel->basic_publish($message,$this->conf['exchange'],$this->conf['routing_dlx']);
//阻塞等待消息确认 (生产者 防止信息丢失)
$this->channel->wait_for_pending_acks_returns();//有返回值
//$this->channel->wait_for_pending_acks();
$this->channel_close();
$this->connection_close();
}catch (Exception $e) {
return $e->getMessage();
}finally{
return true;
}
}
}