rabbitMQ + yii2 (php) Hello World

今天我们学习一下rabbitMQ在php的基本使用。已yii2框架为例。

在这我们将用PHP编写两个程序,生产者发送一个消息,消费者接收信息并打印出来。在使用php-amqplib API时我们会掩盖一些细节,把精力集中在这个非常简单的事情开始。这是一个“Hello World”的消息。

一、安装php-amqplib库
1、composer 安装

{
     "require": {
      "php-amqplib/php-amqplib": "*"
     }
 }

2、git 安装

git clone [email protected]:php-amqplib/php-amqplib.git

二、配置yii2服务端控制台命令(console)。具体配置,请查看下面链接。
https://blog.csdn.net/weixin_36851500/article/details/92798246
在这里插入图片描述
三、现在我们已经安装了php-amqplib库,我们可以写一些代码

目录 /yii2advanced/vendor/yiisoft/yii2/console/controllers 下创建 ProducerController.php和ConsumerController.php

1、发送信息

我们将调用我们消息发送者 ProducerController.php,并调用我们的消息接收者 ConsumerController.php 。消息发送者将要连接RabbitMQ,发送一个消息,然后退出。

  • 在ProducerController.php中,我们需要包含库和使用必要的类:
		use PhpAmqpLib\Connection\AMQPStreamConnection;
		use PhpAmqpLib\Message\AMQPMessage;
  • 然后我们可以建立一个到RabbitMQ服务器的连接:
        $amqp = yii::$app->params['amqp'];
		//建立一个到RabbitMQ服务器的连接
		$this->connection = new AMQPStreamConnection($amqp["host"], $amqp["port"], $amqp["user"], $amqp["password"]);
		$this->channel = $this->connection->channel();
  • 要发送,我们必须为我们发送声明一个队列,然后我们可以向队列发布消息:
		   //接下来,我们创建一个通道,这是大部分的API来完成任务所在。
			$channel->queue_declare('hello', false, false, false, false);
			//构建消息体
			$msg = new AMQPMessage('Hello World!');
			//发送信息
			$channel->basic_publish($msg,'','hello');

			echo " [x] Sent 'Hello World!'\n";
  • 最后,我们关闭通道和连接;
			$channel->close();
			$connection->close();

发送不成功!
如果这是你第一次使用RabbitMQ,并且没有看到“Sent”消息出现在屏幕上,你可能会抓耳挠腮不知所以。这也许是因为没有足够的磁盘空间给代理使用所造成的(代理默认需要1Gb的空闲空间),所以它才会拒绝接收消息。查看一下代理的日志确定并且减少必要的限制。配置文件文档会告诉你如何更改磁盘空间限制(disk_free_limit)。

2、获取数据

那是我们的发送者。我们的接受者获取从RabbitMQ推过来的消息,所以不像发送者发布一个消息,我们将保持运行监听消息并打印出来

扫描二维码关注公众号,回复: 11238781 查看本文章
  • 代码(在 ConsumerController.php )具有几乎相同的包括和加载:
			use PhpAmqpLib\Connection\AMQPStreamConnection;
  • 设置和发送者是一样的,我们打开一个连接和一个通道,然后声明我们将要消耗的队列。请注意,这与发送的队列中的队列相匹配。

然后我们可以建立一个到RabbitMQ服务器的连接:


		    $amqp = yii::$app->params['amqp'];
	
			//建立一个到RabbitMQ服务器的连接
			$this->connection = new AMQPStreamConnection($amqp["host"], $amqp["port"], $amqp["user"], $amqp["password"]);
			$this->channel = $this->connection->channel();

建立通道

			$connection = $this->connection;
			$channel = $this->channel;
			$channel->queue_declare('hello', false, false, false, false);
			echo ' [*] Waiting for messages. To exit press CTRL+C', "\n";

请注意,我们在这里声明队列。因为在发送者之前,我们可以启动接收者,所以我们希望在尝试消费它的消息之前先确保队列的存在。
我们将要告诉服务器从队列中传递消息。我们将定义一个PHP回调将接收服务器发送的消息。请记住,消息是从服务器异步发送到客户端的。

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

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

			while(count($channel->callbacks)) {
				$channel->wait();
			}

			$channel->close();
			$connection->close();

代码块循环 通道( c h a n n e l channel )的回调。无论什么时候我们收到消息我们的回调函数( callback)将传递给接收的消息。

四、整合

  • 现在就可以在终端中运行我们的程序了。启动发送者:
			./yii  rabbitmq-producer/send
  • 然后启动消费者
			./yii rabbitmq-consumer/receive

接收者将打印从发送者通过RabbitMQ发送的消息。接收器将继续运行,等待消息(使用Ctrl-C来中止),所以试着从另一个终端运行发件者。

  • 如果你想查看Rabbitmq队列,并且想知道有多少消息存在其中,你(作为特权用户)可以使用rabbitmqctl 工具
			sudo rabbitmqctl list_queues

五、 源码
1、创建 ProducerController.php 生产者类 actionSend 方法

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * 生产者 发送信息
 */

namespace yii\console\controllers;

use Yii;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\console\Controller;
use yii\console\Exception;
use yii\console\ExitCode;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\test\FixtureTrait;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

/**
 * Manages fixture data loading and unloading.
 *
 * ```
 * #load fixtures from UsersFixture class with default namespace "tests\unit\fixtures"
 * yii fixture/load User
 *
 * #also a short version of this command (generate action is default)
 * yii fixture User
 *
 * #load all fixtures
 * yii fixture "*"
 *
 * #load all fixtures except User
 * yii fixture "*, -User"
 *
 * #load fixtures with different namespace.
 * yii fixture/load User --namespace=alias\my\custom\namespace\goes\here
 * ```
 *
 * The `unload` sub-command can be used similarly to unload fixtures.
 *
 * @author Mark Jebri <[email protected]>
 * @since 2.0
 */
class ProducerController extends Controller
{

	private $channel;
	private  $connection;
	public function init ()
	{

		$amqp = yii::$app->params['amqp'];

		//建立一个到RabbitMQ服务器的连接
		$this->connection = new AMQPStreamConnection($amqp["host"], $amqp["port"], $amqp["user"], $amqp["password"]);
		$this->channel = $this->connection->channel();


	}

	/**
	 * Hello World 发送信息
	 */
	public function actionSend(){
		try {
			//建立一个到RabbitMQ服务器的连接
			$connection = $this->connection;
			$channel = $this->channel;
			//接下来,我们创建一个通道,这是大部分的API来完成任务所在。
			$channel->queue_declare('hello', false, false, false, false);
			//构建消息体
			$msg = new AMQPMessage('Hello World!');
			//发送信息
			$channel->basic_publish($msg,'','hello');

			echo " [x] Sent 'Hello World!'\n";

			$channel->close();
			$connection->close();

		} catch(\Exception $e)
		{
			echo $e->getMessage();
		}
	}

}

2、ConsumerController.php 消费者文件类 actionReceive 方法

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * 消费者 接收信息
 */

namespace yii\console\controllers;

use Yii;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\console\Controller;
use yii\console\Exception;
use yii\console\ExitCode;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use yii\test\FixtureTrait;
use common\tools\Pusher;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

/**
 * Manages fixture data loading and unloading.
 *
 * ```
 * #load fixtures from UsersFixture class with default namespace "tests\unit\fixtures"
 * yii fixture/load User
 *
 * #also a short version of this command (generate action is default)
 * yii fixture User
 *
 * #load all fixtures
 * yii fixture "*"
 *
 * #load all fixtures except User
 * yii fixture "*, -User"
 *
 * #load fixtures with different namespace.
 * yii fixture/load User --namespace=alias\my\custom\namespace\goes\here
 * ```
 *
 * The `unload` sub-command can be used similarly to unload fixtures.
 *
 * @author Mark Jebri <[email protected]>
 * @since 2.0
 */
class ConsumerController extends Controller
{
	private $channel;
	private  $connection;
	public function init ()
	{


		$amqp = yii::$app->params['amqp'];

		//建立一个到RabbitMQ服务器的连接
		$this->connection = new AMQPStreamConnection($amqp["host"], $amqp["port"], $amqp["user"], $amqp["password"]);
		$this->channel = $this->connection->channel();


	}
	/**
	 * Loads the specified fixture data.
	 * @return bool
	 * Hello World 接收信息
	 */
	public function actionReceive(){

		try {
			//$channel = $this->channel;
			//var_dump($this->channel);exit;
			//设置和发送者是一样的,我们打开一个连接和一个通道,然后声明我们将要消耗的队列。请注意,这与发送的队列中的队列相匹配。
			//建立一个到RabbitMQ服务器的连接
			$connection = $this->connection;
			$channel = $this->channel;
			$channel->queue_declare('hello', false, false, false, false);
			echo ' [*] Waiting for messages. To exit press CTRL+C', "\n";

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

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

			while(count($channel->callbacks)) {
				$channel->wait();
			}

			$channel->close();
			$connection->close();


		} catch(\Exception $e)
		{
			echo $e->getMessage();
		}
	}



}

有兴趣的话,可以多了解一下其他的文章:
https://xiaoxiami.gitbook.io/rabbitmq_into_chinese_php/ying-yong-jiao-cheng/php-ban/1-hello_world

猜你喜欢

转载自blog.csdn.net/weixin_36851500/article/details/92759631