php中rabbitmq的使用

一、安装:

1.安装rabbitmq运行环境

1)下载地址:https://www.erlang.org/downloads

2)下载完成之后,安装,直接下一步、下一步。

3)安装完成或,配置环境变量。

​ 变量名:ERLANG_HOME

​ 变量值:根据你安装的路径,如果都是下一步的话路径就是:C:\Program Files\erl-23.0

image-20200806165944173.png

配置path路径:


image-20200806170920926.png

2.安装rabbitmq。

​ 1.下载地址:https://www.rabbitmq.com/download.html。

​ 2)下载完成之后,安装,直接下一步、下一步。

​ 3)进入安装路径,如果是直接下一步的话,路径是:C:\Program Files\RabbitMQ Server\rabbitmq_server-3.8.6\sbin,执行rabbitmq-plugins enable rabbitmq_management开启管理界面

image-20200806171124974.png

4)启动。


image-20200806171300632.png

点击右键,用管理员的身份运行。

5)然后再浏览器中输入:http://localhost:15672/#/exchanges,地址,就可以看到如下界面了

image-20200806171504456.png

6)输入rabbitmq的初始密码:Username:guest,Password:guest,就可以看到如下界面了:

image-20200806171915957.png

​7)rabbitmq登录进来,新建一个用户。


image-20200806173012631.png

比如我新建的 Username:tianbin_test ,password:tianbin_test

8)选择标签(选Admin)


image-20200806173232637.png

9)用户添加成功。

image-20200806173348492.png

10)没有虚拟主机,新建一个虚拟主机


image-20200806173441121.png

11)我这里填写的

image-20200806173557821.png

12)添加成功的界面如下:

image-20200806173711948.png

13)设置权限


image-20200806173910136.png

image-20200806173950145.png

image-20200806174007705.png

14)查看权限

image-20200806174131316.png

15)over。

二.rabbitmq的五种模式。

1.简单模式

image-20200806174254461.png

说明:

1.生产者将消息交给默认的交换器(AMQP default)
2 .交换器获取消息后交给绑定这个生产者的队列(关系是通过队列名称完成)
3.监听当前队列的消费者获取消息,执行消费逻辑

使用:

1)使用tianbin_test用户登录。

image-20200807091313376.png

2)设置权限

image-20200807093029571.png

3).进入某个文件夹

​ 在控制台中执行:composer init

​ 然后再执行 :composer require php-amqplib/php-amqplib

​ 代码结果如下:


image-20200807093512995.png

新建文件夹和文件,最终结果如下:

[图片上传失败...(image-d2f1d-1597113673243)]

simple文件夹中customer文件内容如下:

    channel();
$channel->queue_declare($exchange,false,false, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
};

$channel->basic_consume($exchange, '', false, false, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

simple文件夹中producter文件内容如下:

channel();
$AMQPChannel->queue_declare($exchange,false,false, false, false);
$message = '简单模式';
$AMQPMessage = new AMQPMessage($message,array('content_type' => 'text/plain'));
$AMQPChannel->basic_publish($AMQPMessage,'',$exchange);
$AMQPChannel->close();
$connection->close();

执行:php producter.php,结果如下:

image-20200807094501268.png

image-20200807094532762.png

​ 执行:php customer.php,结果如下:

image-20200807094649946.png

备注:如果要手动进行消息确认(就是确定该消息有没有被消费成功)

请使用如下代码:

customer代码如下

channel();
$channel->queue_declare($exchange,false,true, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
  //这里抛异常,该消息不会被消费
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};

$channel->basic_consume($exchange, '', false, false, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

producter代码如下

channel();
//$AMQPChannel->queue_declare($exchange,false,false, false, false);
$AMQPChannel->queue_declare($exchange,false,true, false, false);
$message = '简单模式';
$AMQPMessage = new AMQPMessage($message, array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
$AMQPChannel->basic_publish($AMQPMessage,'',$exchange);
$AMQPChannel->close();
$connection->close();

演示:

1)执行:php producter.php,结果如下:

image-20200811100017075.png

image-20200811100036336.png

2)修改customer,结果如下:

image-20200811100623188.png

3)执行

php customer.php

4)查看

image-20200811100649017.png

5)结果如下:


image-20200811100720681.png

7)如果我将异常去掉,执行

image-20200811100836539.png

发现该消息已经被消费了。

2.工作模式

image-20200807095109142.png

说明:

  1. 生产者将消息交个交换机
  2. 交换机交给绑定的队列
  3. 队列由多个消费者同时监听,只有其中一个能够获取这一条消息,形成了资源的争抢,谁的资源空闲大,争抢到的可能越大;

使用:

新建work目录和文件,最终目录结果如下


image-20200807095038595.png

2)代码如下:

work文件夹producter的文件内容如下:

channel();
$AMQPChannel->queue_declare($exchange,false,true, false, false);
$message = '';

for ($i =0;$i<50;$i++){
    $message= '工作模式'.(string)$i;
    $AMQPMessage = new AMQPMessage($message,array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
    $AMQPChannel->basic_publish($AMQPMessage,'',$exchange);
}
$AMQPChannel->close();
$connection->close();

work文件夹customerOne的文件内容如下:

channel();
$channel->queue_declare($exchange, false, true, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
    echo " [x] Done\n";
    sleep(10);
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};

$channel->basic_consume($exchange, '', false, false, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

work文件夹customerTwo的文件内容如下:

channel();
$channel->queue_declare($exchange,false,true, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
    echo " [x] Done\n";
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};

$channel->basic_consume($exchange, '', false, false, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

3)执行

php customerOne.php

php customerTwo.php

php producter.php

4)结果如下:

image-20200807143343587.png
image-20200807143521735.png

发现没有多劳多得。

6)修改代码

customerTwo的文件内容如下:

channel();
$channel->queue_declare($exchange,false,true, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
    echo " [x] Done\n";
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_qos(null,1,null);//每个消费者只能处理一条信息
$channel->basic_consume($exchange, '', false, false, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

customerOne文件内容如下:

channel();
$channel->queue_declare($exchange, false, true, false, false);
$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
    echo " [x] Done\n";
    sleep(10);
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_qos(null,1,null);//每个消费者只能处理一条信息
$channel->basic_consume($exchange, '', false, false, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

7)执行

php customerOne.php

php customerTwo.php

php producter.php

8)结果如下:

image-20200807144737958.png
image-20200807145128546.png

9)over。

3.发布订阅模型

image-20200810091400152.png

说明:

1 .生产者扔给交换机消息
2 .交换机根据自身的类型(fanout)将会把所有消息复制同步到所有与其绑定的队列
3 .每个队列可以有一个消费者,接收消息进行消费逻辑

使用:

1)新建fanout文件夹和文件,最终结构如下:

image-20200810091924989.png

2)代码如下:

customerOne文件内容如下:

channel();
$channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);

$channel->queue_bind($queue_name, $exchange);
$callback = function ($msg) {
    echo ' [x] ', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

customerTwo的文件内容如下:

channel();
$channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);

$channel->queue_bind($queue_name, $exchange);
$callback = function ($msg) {
    echo ' [x] ', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

producter文件内容如下:

channel();
$channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);

$channel->queue_bind($queue_name, $exchange);
$callback = function ($msg) {
    echo ' [x] ', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

3)执行

php customerOne.php

php customerTwo.php

php producter.php

4)结果如下:

​ producter结果:

image-20200810171026177.png

customerOne结果如下:

image-20200810171145071.png

customerTwo结果如下:

image-20200810171222751.png

4.路由模式

image-20200810171422750.png

说明:

1.生产者还是将消息发送给交换机,消息携带具体的路由key(routingKey)
2.交换机类型direct,将接收到的消息中的routingKey,比对与之绑定的队列的routingKey
3.消费者监听一个队列,获取消息,执行消费逻辑

使用:

1)新建direct文文件夹和文件,最终结果如下:

image-20200810171827274.png

2)代码如下:

customerOne代码如下:

channel();
$channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);

$channel->queue_bind($queue_name, $exchange);
$callback = function ($msg) {
    echo ' [x] ', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

customerTwo代码如下:

channel();
$channel->exchange_declare($exchange, AMQPExchangeType::FANOUT, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);
$channel->queue_bind($queue_name, $exchange);
$callback = function ($msg) {
    echo ' [x] ', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

producter代码如下:

channel();
$AMQPChannel->exchange_declare($exchange, AMQPExchangeType::FANOUT,false , false, false);
$message = 'fanout,hello';
$AMQPMessage = new AMQPMessage($message);
$AMQPChannel->basic_publish($AMQPMessage, $exchange);
echo ' [x] Sent ', $message, "\n";
$AMQPChannel->close();
$connection->close();

3)最终结果如下:

producter如下:

image-20200810175905835.png

customerTwo如下:

image-20200810180018174.png

customerOne如下:

image-20200810180116260.png

4)over。

5.主题 模式

image-20200811090444868.png

说明:

1.生产端发送消息,消息携带具体的路由key
2 .交换机的类型topic
3 .队列绑定交换机不在使用具体的路由key而是一个范围值

*表示一个字符串(不能携带特殊符号)

表示任意字符串

使用:

1)新建topic文件夹和文件,最终结果如下:

image-20200811091554027.png

2)代码如下:

customerOne代码如下:

channel();
$binding_keys = [];
$binding_keys[] = '#';
$binding_keys[] = "*";
$channel->exchange_declare($exchange, AMQPExchangeType::TOPIC, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);
foreach ($binding_keys as $binding_key) {
    $channel->queue_bind($queue_name, $exchange, $binding_key);
}
$callback = function ($msg) {
    echo ' [one] ', $msg->delivery_info['routing_key'], ':', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

customerTwo代码如下:

`customerOne`代码如下:channel();
$binding_keys = [];
$binding_keys[] = 'insert.*';
$channel->exchange_declare($exchange, AMQPExchangeType::TOPIC, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);
foreach ($binding_keys as $binding_key) {
    $channel->queue_bind($queue_name, $exchange, $binding_key);
}
$callback = function ($msg) {
    echo ' [one] ', $msg->delivery_info['routing_key'], ':', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

producter代码如下:

channel();
$binding_keys = [];
$binding_keys[] = 'insert.*';
$channel->exchange_declare($exchange, AMQPExchangeType::TOPIC, false, false, false);
list($queue_name, ,) = $channel->queue_declare($queue_name, false, false, true, false);
foreach ($binding_keys as $binding_key) {
    $channel->queue_bind($queue_name, $exchange, $binding_key);
}
$callback = function ($msg) {
    echo ' [one] ', $msg->delivery_info['routing_key'], ':', $msg->body, "\n";
};

$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_consuming()) {
    $channel->wait();
}

3)最终结果如下:

producter结果如下:

image-20200811092326243.png

customerOne结果如下:

image-20200811092440334.png

customerTwo结果如下:

image-20200811092512071.png

源码链接如下:
项目源码

你可能感兴趣的:(php中rabbitmq的使用)