zoukankan      html  css  js  c++  java
  • 代码实现RabbitMQ死信队列的创建

    前言:

        之前有写过死信队列的使用场景以及通过管控台创建死信。这次就通过代码实现死信队列的创建,同时也分享一下RabbitMQ封装的类。

    准备:

    1. 先准备一个死信队列(最后用来消费)的参数配置,包括虚拟机,交换机,队列,有效时间等,如下。

    2. 按照上面在RabbitMQ中创建虚拟机和交换机,死信队列。并让交换机与死信队列绑定,操作方法前面有介绍。

    3. 这里就直接提供rabbitMQ操作的基本封装的类,包括一个基类,生产者类,消费者类。

    3.1. 基类。

    <?php
    namespace rabbitmq;
     
    /** Member
     *  AMQPChannel
     *  AMQPConnection
     *  AMQPEnvelope
     *  AMQPExchange
     *  AMQPQueue
     * Class BaseMQ
     * @package rabbitMQ
     */
    class BaseMQ
    {
        /** MQ Channel
        * @var AMQPChannel
        */
        public $AMQPChannel ;
    
        /** MQ Link
        * @var AMQPConnection
        */
        public $AMQPConnection ;
    
        /** MQ Envelope
        * @var AMQPEnvelope
        */
        public $AMQPEnvelope ;
    
        /** MQ Exchange
        * @var AMQPExchange
        */
        public $AMQPExchange ;
    
        /** MQ Queue
        * @var AMQPQueue
        */
        public $AMQPQueue ;
    
        /** conf
        * @var
        */
        public $conf ;
    
        /** exchange
        * @var
        */
        public $exchange ;
    
        /**
         * queue
         * @var
         */
        public $queue;
    
        /**
         * routes
         * @var
         */
        public $route;
    
        /**
         * queue_args
         * @var
         */
        public $queueArgs;
    
    
        /** link
        * BaseMQ constructor.
        * @throws AMQPConnectionException
        */
        public function __construct($host,$options,$args = [])
        {
    
            $config = include 'config/config.php';
    
            if (!$config)
                throw new AMQPConnectionException('config error!');
    
    
            $this->host  = array_merge($config,$host);
    
            isset($options['vhost']) && $this->host['vhost'] = $options['vhost'];
    
            $this->exchange = $options['exchange'];
    
            $this->queue = $options['queue'];
            
            $this->route = $options['route'];
    
            $this->queueArgs = $args;
    
            $this->AMQPConnection = new AMQPConnection($this->host);
    
            if (!$this->AMQPConnection->connect())
                throw new AMQPConnectionException("Cannot connect to the broker!
    ");
        }
    
        /**
        * close link
        */
        public function close()
        {
    
            $this->AMQPConnection->disconnect();
        }
    
        /** Channel
        * @return AMQPChannel
        * @throws AMQPConnectionException
        */
        public function channel()
        {
    
            if (!$this->AMQPChannel) {
                $this->AMQPChannel = new AMQPChannel($this->AMQPConnection);
            }
    
            return $this->AMQPChannel;
        }
    
        /** Exchange
        * @return AMQPExchange
        * @throws AMQPConnectionException
        * @throws AMQPExchangeException
        */
        public function exchange()
        {
    
            if (!$this->AMQPExchange) {
    
                $this->AMQPExchange = new AMQPExchange($this->channel());
    
                $this->AMQPExchange->setName($this->exchange);
            }
    
            return $this->AMQPExchange ;
        }
    
        /** queue
        * @return AMQPQueue
        * @throws AMQPConnectionException
        * @throws AMQPQueueException
        */
        public function queue()
        {
    
            if (!$this->AMQPQueue) {
                $this->AMQPQueue = new AMQPQueue($this->channel());
            }
    
            return $this->AMQPQueue ;
        }
    
        /** Envelope
        * @return AMQPEnvelope
        */
        public function envelope()
        {
    
            if (!$this->AMQPEnvelope) {
                $this->AMQPEnvelope = new AMQPEnvelope();
            }
    
            return $this->AMQPEnvelope;
        }
    }

    3.2. 生产者类。

    <?php
    //生产
    namespace rabbitmq;
    
    class ProductMQ extends BaseMQ
    {
    
    	/** 只控制发送成功 不接受消费者是否收到
    	* @throws AMQPChannelException
    	* @throws AMQPConnectionException
    	* @throws AMQPExchangeException
    	*/
    	public function publish($message)
    	{
    
    		$message = is_array($message)?json_encode($message):$message;
    
    		//频道
    		$channel = $this->channel();
    		//创建交换机对象
    		$ex = $this->exchange();
    
    		return $ex->publish($message, $this->route, AMQP_NOPARAM, array('delivery_mode' => 2));
    	}
    }

    3.3. 消费者。

    <?php
    namespace rabbitmq;
    
    class ConsumerMQ extends BaseMQ
    {
    
    	/** 接受消息 如果终止 重连时会有消息
    	* @throws AMQPChannelException
    	* @throws AMQPConnectionException
    	* @throws AMQPExchangeException
    	* @throws AMQPQueueException
    	*/
    	public function run($processMessage)
    	{
    
    		// 创建交换机
    		$ex = $this->exchange();
    		// direct类型
    		$ex->setType(AMQP_EX_TYPE_DIRECT); 
    		// 持久化
    		$ex->setFlags(AMQP_DURABLE);
    		// 不存在就发布
    		$ex->declareExchange();
    		// 创建队列
    		$q = $this->queue();
    		// 设置队列名称
    		$q->setName($this->queue);
    		// 持久化
    		$q->setFlags(AMQP_DURABLE); 
    
    		// 队列参数
    		is_array($this->queueArgs) && $q->setArguments($this->queueArgs);
    
    		//echo "Message Total:".$q->declareQueue()."
    ";
    		$q->declareQueue();
    
    		//绑定交换机与队列,并指定路由键
    		// echo 'Queue Bind: '.$q->bind($this->exchange, $this->route)."
    ";
    		$q->bind($this->exchange, $this->route);
    
    		//阻塞模式接收消息
    		// echo "Message:
    ";
    		
    		if (!is_null($processMessage)) {
    
    			while (True) {
    				$q->consume($processMessage);
    			}
    		}
    
    		$this->close();
    	}
    }
    

    编码:

         上面的死信队列已经创建好了,接下来主要就是通过代码创建一个用于直接生产消息的普通队列,但是这个队列需要设置三个参数。

    x-dead-letter-exchange:       关联死信的交换机
    x-dead-letter-routing-key     关联死信的路由key
    x-message-ttl                 当前队列消息的有效期,也就是多久后消息自动进行死信队列,并且从本队列删除

       1. 代码部分:

    public function addToDlx()
        {
            $host = [
                'host' => '127.0.0.1',
                'port' => '5672',
                'login' => 'guest',
                'password' => 'guest',
                'vhost' => 'report',
                'heartbeat' => 60
            ];
    
            // 普通队列
            $normal = [
                'vhost' => 'report',                    // 虚拟机
                'exchange' => 'normal',                 // 交换机
                'route' => 'normal_route',              // 路由key - 用于交换机与队列进行绑定
                'queue' => 'normal_queue',              // 队列
                'expire' => 1000*60,                    // 有效时间单位:毫秒   - 1分钟
            ];
    
            // 死信队列
            $normal_dlx = [
                'vhost' => 'report',
                'exchange' => 'normal_dlx',
                'route' => 'normal_dlx_route',
                'queue' => 'normal_dlx_queue'
            ];
    
            // 给普通队列关联死信队列,携带的参数
            $dlx_args = [
                'x-dead-letter-exchange' => $normal_dlx['exchange'],
                'x-dead-letter-routing-key' => $normal_dlx['route'],
                'x-message-ttl' => $normal['expire'],
            ];
    
            //////////////// 通过消费者方式创建死信队列/////////////
            $dlx_mq = new ConsumerMQ($host,$normal,$dlx_args);
            $dlx_mq->run(null);
            ////////////////////////////////////////////////////////
    
    
            //////////////// 将消息放入普通队列/////////////////////
            $mq = new ProductMQ($host, $normal);
    
            $param = json_encode([
                'name' => 'test',
                'id' => 11568,
                'remark' => '测试一下'
            ]);
    
            $mq->publish($param);
    
            $mq->close();
            ////////////////////////////////////////////////////////
        }

    2. 测试结果:

           通过postman点击上面接口,控制台就可以看出多出了一个normal队列,并且队列的 Features 为“ D TTL DLX DLK ”,$param的消息也会首先进入“normal”队列。

    2. 1分钟后(自己设置的),normal的消息会失效,进而开始添加到了死信队列“normal_dxl”,可以点击死信查看最新的消息信息。

  • 相关阅读:
    安卓开发环境搭建
    css3实现漂亮的按钮链接
    mouseover与mouseenter的区别
    踩了一个在body上添加多个代理事件的坑
    javascript与生活:papago行车记录仪播放器golife无卫星图修复方法
    grunt入门之windows下搭建一个最基本的grunt项目
    一个简单的跨浏览器的弹出窗口的实现
    如何查询mysql中执行效率低的sql语句
    用PHP读写音频文件的信息(支持WMA和MP3)
    PHP功能类[获取客户端IP、页面跳转]
  • 原文地址:https://www.cnblogs.com/zerofc/p/13873302.html
Copyright © 2011-2022 走看看