<?php
namespace app\rabbitmq\controller;
use think\Controller;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: 連接rabbitmq的一些操作,通用
*/
class BasicConnect extends Controller
{
public $mq_host = '192.168.XX.XXX';
public $mq_port1 = 5672;
public $mq_port2 = 5672;
public $mq_port3 = 5673;
public $mq_user = 'XXXX';
public $mq_passwd = 'XXXX';
public $mq_vhost = '/';
public $connection = '';
public function __construct(){
$host = [
[
'host' => $this->mq_host,
'port' => $this->mq_port1,
'user' => $this->mq_user,
'password' => $this->mq_passwd,
'vhost' => $this->mq_vhost
],
[
'host' => $this->mq_host,
'port' => $this->mq_port2,
'user' => $this->mq_user,
'password' => $this->mq_passwd,
'vhost' => $this->mq_vhost
],
[
'host' => $this->mq_host,
'port' => $this->mq_port3,
'user' => $this->mq_user,
'password' => $this->mq_passwd,
'vhost' => $this->mq_vhost
],
];
$options = [];
$this->connection = AMQPStreamConnection::create_connection($host,$options);
}
}
BasicConnect.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: 簡單模式---生產者
* 注意:一個生產者,一個消費者,簡單模式。
*/
class SimpleProducer extends BasicConnect
{
public $exchange = 'simple_test_exchange';
public $queue = 'simple_test_queue';
public function __construct(){
parent::__construct();
}
public function Index(){
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: true 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 可以通過其他通道訪問隊列(the queue can be accessed in other channels)
* auto_delete: false 一旦通道關閉,隊列將不會被刪除。(the queue won't be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, true, false, false);
/**
* name: $exchange
* type: direct
* passive: false
* durable: true 服務器重啓後交換機將仍存在(the exchange will survive server restarts)
* auto_delete: false 一旦頻道關閉,將不會刪除交換。(the exchange won't be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::DIRECT, false, true, false);
$channel->queue_bind($this->queue, $this->exchange);
# 僅發送1條數據
// $messageBody = 'it is a simple message';
// $message = new AMQPMessage($messageBody,['content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]);
// $channel->basic_publish($message, $this->exchange);
# 發送多條數據(注意,僅第一次創建AMQPMessage對象,其它通過setBody複用前面創建的對象)
$properties = ['content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT];
for($i=1;$i<10;$i++){
$messageBody = 'it is a simple message:'.$i;
if( $i == 1){
$message = new AMQPMessage($messageBody, $properties);
}else{
$message->setBody($messageBody);
}
$channel->basic_publish($message, $this->exchange);
}
$channel->close();
$this->connection->close();
exit;
}
}
SimpleProducer.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: 簡單模式---消費者
*/
class SimpleConsumer extends BasicConnect
{
public $exchange = 'simple_test_exchange';
public $queue = 'simple_test_queue';
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱
* passive: false
* durable: true 服務器重啓後隊列將仍存在(the queue will survive server restarts)
* exclusive: false 可以通過其他通道訪問隊列(the queue can be accessed in other channels)
* auto_delete: false 一旦通道關閉,隊列將不會被刪除。(the queue won't be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, true, false, false);
/**
* name: $exchange
* type: direct
* passive: false
* durable: true 服務器重啓後交換機將仍存在(the exchange will survive server restarts)
* auto_delete: false 一旦頻道關閉,將不會刪除交換。(the exchange won't be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::DIRECT, false, true, false);
$channel->queue_bind($this->queue, $this->exchange);
/**
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
SimpleConsumer.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: fanout形式---生產者
* 注意:
1)、生產者不需要定義隊列名稱,而消費者必須定義隊列名稱
2)、工作隊列模式(Work Queue):一個生產者,多個消費者同時消費這些數據,即輪詢消費(啓動1個FanoutProducer,啓動多個FanoutConsumer1)
3)、發佈/訂閱模式(Publish/Subscribe):一個生產者,多個消費者獲得相同的數據,即廣播方式(啓動1個FanoutProducer,啓動多個FanoutConsumer1{需要注意修改其中的queue名稱,保證不一致})
*/
class FanoutProducer extends BasicConnect
{
public $exchange = 'fanout_test_exchange';
public function __construct(){
parent::__construct();
}
public function Index(){
$channel = $this->connection->channel();
/**
* name: $exchange 交換機名稱
* type: fanout 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::FANOUT, false, false, true);
$messageBody = 'I am a fanout message';
$message = new AMQPMessage($messageBody, ['content_type' => 'text/plain']);
$res = $channel->basic_publish($message, $this->exchange);
$channel->close();
$this->connection->close();
exit;
}
}
FanoutProducer.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: fanout形式--消費者1
*/
class FanoutConsumer1 extends BasicConnect
{
public $exchange = 'fanout_test_exchange';
public $queue = 'fanout_test_queue1';#注意就這個隊列名不同
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱,在fanout類型的交換機中必須唯一(should be unique in fanout exchange.)
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: false 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 隊列可能被其他通道訪問(the queue might be accessed by other channels)
* auto_delete: true 一旦通道關閉,隊列將被刪除(the queue will be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, false, false, true);
/**
* name: $exchange 交換機名稱
* type: fanout 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::FANOUT, false, false, true);
$channel->queue_bind($this->queue, $this->exchange);
/*
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
FanoutConsumer1.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: fanout形式--消費者2
*/
class FanoutConsumer2 extends BasicConnect
{
public $exchange = 'fanout_test_exchange';
public $queue = 'fanout_test_queue2';#注意就這個隊列名不同
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱,在fanout類型的交換機中必須唯一(should be unique in fanout exchange.)
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: false 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 隊列可能被其他通道訪問(the queue might be accessed by other channels)
* auto_delete: true 一旦通道關閉,隊列將被刪除(the queue will be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, false, false, true);
/**
* name: $exchange 交換機名稱
* type: fanout 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::FANOUT, false, false, true);
$channel->queue_bind($this->queue, $this->exchange);
/*
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
FanoutConsumer2.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: direct形式---生產者
*/
class DirectProducer extends BasicConnect
{
public $exchange = 'direct_test_exchange';
public function __construct(){
parent::__construct();
}
public function Index(){
$channel = $this->connection->channel();
/**
* name: $exchange 交換機名稱
* type: DIRECT 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::DIRECT, false, false, true);
$messageBody = 'I am a direct message';
$message = new AMQPMessage($messageBody, ['content_type' => 'text/plain']);
$channel->basic_publish($message, $this->exchange, 'direct_key1');
$channel->close();
$this->connection->close();
exit;
}
}
DirectProducer.php
https://www.jianshu.com/p/fdb195698a5a
https://my.oschina.net/u/3698467/blog/1825316
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: topic形式--消費者1
* @user: dingling
* @version: V1.0
* @date: 20200528
*/
class DirectConsumer1 extends BasicConnect
{
public $exchange = 'direct_test_exchange';
public $queue = 'direct_test_queue1';#注意就這個隊列名不同
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱,在fanout類型的交換機中必須唯一(should be unique in fanout exchange.)
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: false 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 隊列可能被其他通道訪問(the queue might be accessed by other channels)
* auto_delete: true 一旦通道關閉,隊列將被刪除(the queue will be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, false, false, true);
/**
* name: $exchange 交換機名稱
* type: DIRECT 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::DIRECT, false, false, true);
$channel->queue_bind($this->queue, $this->exchange, 'direct_key1');
/*
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
DirectConsumer1.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: topic形式---生產者
* 注意:
*/
class TopicProducer extends BasicConnect
{
public $exchange = 'topic_test_exchange';
public function __construct(){
parent::__construct();
}
public function Index(){
$channel = $this->connection->channel();
/**
* name: $exchange 交換機名稱
* type: TOPIC 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::TOPIC, false, false, true);
$messageBody = 'I am a TOPIC message';
$message = new AMQPMessage($messageBody, ['content_type' => 'text/plain']);
$res = $channel->basic_publish($message, $this->exchange, 'key.1.2');#routing_key設置爲key.1.2,只有TopicConsumer2{'key.#'}消費者能收到
#$res = $channel->basic_publish($message, $this->exchange, 'key.1');#routing_key設置爲key.1,TopicConsumer1{'key.*'}和TopicConsumer2{'key.#'}消費者都可以收到
$channel->close();
$this->connection->close();
exit;
}
}
TopicProducer.php
*(星號)可以代替一個任意標識符 ;#(井號)可以代替零個或多個標識符。
https://blog.csdn.net/a491857321/article/details/50616323 (JAVA實現)
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: topic形式--消費者1
*/
class TopicConsumer1 extends BasicConnect
{
public $exchange = 'topic_test_exchange';
public $queue = 'topic_test_queue1';#注意就這個隊列名不同
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱,在fanout類型的交換機中必須唯一(should be unique in fanout exchange.)
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: false 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 隊列可能被其他通道訪問(the queue might be accessed by other channels)
* auto_delete: true 一旦通道關閉,隊列將被刪除(the queue will be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, false, false, true);
/**
* name: $exchange 交換機名稱
* type: TOPIC 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::TOPIC, false, false, true);
$channel->queue_bind($this->queue, $this->exchange, 'key.*');
/*
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
TopicConsumer1.php
<?php
namespace app\rabbitmq\controller;
use think\Controller;
use app\rabbitmq\controller\BasicConnect as BasicConnect;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Exchange\AMQPExchangeType;
/**
* @desc: topic形式--消費者2
*/
class TopicConsumer2 extends BasicConnect
{
public $exchange = 'topic_test_exchange';
public $queue = 'topic_test_queue2';#注意就這個隊列名不同
public function __construct(){
parent::__construct();
}
public function Index(){
$consumerTag = 'consumer' . getmypid();
$channel = $this->connection->channel();
/**
* name: $queue 隊列名稱,在fanout類型的交換機中必須唯一(should be unique in fanout exchange.)
* passive: false 不檢查是否存在同名隊列(don't check if a queue with the same name exists)
* durable: false 服務器重啓後隊列將無法生存(the queue will not survive server restarts)
* exclusive: false 隊列可能被其他通道訪問(the queue might be accessed by other channels)
* auto_delete: true 一旦通道關閉,隊列將被刪除(the queue will be deleted once the channel is closed.)
*/
$channel->queue_declare($this->queue, false, false, false, true);
/**
* name: $exchange 交換機名稱
* type: TOPIC 交換機類型
* passive: false 是否檢查存在同名的交換機(don't check is an exchange with the same name exists)
* durable: false 服務器重啓後銷燬交換機(the exchange won't survive server restarts)
* auto_delete: true 管道(channel)關閉後將銷燬交換機(the exchange will be deleted once the channel is closed.)
*/
$channel->exchange_declare($this->exchange, AMQPExchangeType::TOPIC, false, false, true);
$channel->queue_bind($this->queue, $this->exchange, 'key.#');
/*
* queue: 隊列名稱,從何處獲取消息的隊列(Queue from where to get the messages)
* consumer_tag: 消費者標識符(Consumer identifier)
* no_local: 不接收此消費者發佈的消息。(Don't receive messages published by this consumer.)
* no_ack: 如果設置爲真,則此用戶將使用自動確認模式(If set to true, automatic acknowledgement mode will be used by this consumer. See https://www.rabbitmq.com/confirms.html for details.)
* exclusive: 請求獨佔使用者訪問,這意味着只有此使用者可以訪問隊列(Request exclusive consumer access, meaning only this consumer can access the queue)
* nowait: 不要等待服務器響應。如果出現錯誤,服務器將引發通道異常(don't wait for a server response. In case of error the server will raise a channel exception)
* callback: 回調函數(A PHP Callback)
*/
$channel->basic_consume($this->queue, $consumerTag, false, false, false, false, [new FanoutConsumer1(),'process_message']);
register_shutdown_function([new FanoutConsumer1(),'shutdown'], $channel, $this->connection);
// 循環,只要通道已註冊回調(Loop as long as the channel has callbacks registered)
while ($channel->is_consuming()) {
$channel->wait();
}
exit;
}
/**
* 回調函數
*/
public function process_message($message){
echo "\n--------\n";
echo $message->body;
echo "\n--------\n";
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 發送字符串“quit”通知消費者退出。(Send a message with the string "quit" to cancel the consumer.)
if ($message->body === 'quit') {
$message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']);
}
}
/**
* @param \PhpAmqpLib\Channel\AMQPChannel $channel
* @param \PhpAmqpLib\Connection\AbstractConnection $connection
*/
public function shutdown($channel, $connection)
{
$channel->close();
$connection->close();
}
}
TopicConsumer2.php