PHP RabbitMQ简单使用

<?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();
    }




}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值