一、RabbitMQ安装
- windows安装
下载地址:
https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.3/rabbitmq-server-3.8.3.exe
https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.3/rabbitmq-server-windows-3.8.3.zip
2.linux安装
下载地址:
https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.3/rabbitmq-server_3.8.3-1_all.deb
Centos8:
Centos7:
Centos6:
OpenSUSE:
SLEX 11x:
二、RabbitMQ配置
- 下载Erlang并安装
Erlang下载地址:https://www.erlang.org/downloads
按照你的自己的环境,下载合适的版本并安装即可。
windows相对来说安装比较简单,和普通软件的安装没有区别,按照提示向下进行即可。
Linux安装:需要下载源码,并进行编译安装,这个会在另外的文章中进行说明
三、RabbitMQ原理与消息队列
- 消息:是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。
- 消息队列:消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到消息队列中而不用管谁来取,消息使用者只管从消息队列中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。
- 用途:在不同的进程或线程之间进行通讯。
- 主流的消息队列:
RabbitMQ、ActiveMq、ZeroMq、kafka、RocketMQ(阿里开源)
本文主要介绍RabbitMQ。
RabbitMQ是应用程序之间通讯的一种方法,是建立在AMQP协议基础上的,使用Erlang语言开发的,完整且可复制的企业消息系统。
支持系统:windows,linux,macOX等。
开发语言支持:ruby,python,java,php,. net,C/C++,Node.js等。
AMQP:Advanced Message Queue Protocol(高级消息队列协议),是一个提供统一消息服务的应用层标准高级消息队列协议。
四、RabbitMQ特性
RabbitMQ起源于金融系统,用于在分布式系统中存储并转发消息,在易用性、扩展性、高可用性等方面表现不俗。
具体特性包括:
- 可靠性(Reliability):使用一些机制来保证可靠性,如:持久化,传输确认,发布确认等。
- 灵活的路由(Flexible Routing):在消息进入队列之前,通过exchange来路由消息。RabbitMQ默认再系统中提供了一些路由以供使用,对于复杂的路由可以将多个exchange绑在一起,也通过插件机制来实现自己的路由。
- 高可用(Highly Available Queues):队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
- 多种协议(Multi-protocol):RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。
- 多语言客户端(Many Clients):RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
- 管理界面(Management UI):RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。
- 跟踪机制(Tracing):如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。
- 插件机制(Plugin System):RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
五、RabbitMQ基本概念:
AMQP:Advanced Message Queue Protocol(高级消息队列协议),是一个提供统一消息服务的应用层标准高级消息队列协议。
Exchange:交换机,用来接收生成者消息,并路由给与交换机绑定的队列。
Queue:消息队列,用来存储和消息,并对消息进行顺序排列的队列,是消息的容器,也是消息的终点,消费者将消息存储到消息队列后即可返回。消费者,从这里取用消息。
Broker:消息队列服务器实体(这里可以理解为实体机)
Virtual Host:虚拟主机,一个虚拟机里可以存在多个交换机,和消息队列,他可以共享服务器的加密信息和鉴权认证等,也就是说鉴权和加密是以虚拟机为单位的,不能单独对队列进行这些操作。
Connection:链接:一个网络连接
Channel:通道或信道多路复用连接中的一条独立的双向数据流通道,是建立在真实的TCP连接内地虚拟连接,可以安排每隔进程分配一个信道,也可以安排每隔线程分配一个信道。
Binding:绑定,即exchange与queue之间的绑定关系
Consumer:消费者,这里是指对队列内容进行消费(取出消息,并进行相应的处理)的应用程序,可以是一个进程,也可以是一个线程。
Publisher:生成者,这里是指产生消息的应用程序,可以是进程,也可以是线程
Message:消息,这里是指生产者产生并存储于队列的数据。
六、RabbitMQ在PHP中的应用
- AMQP扩展安装
扩展下载地址:http://pecl.php.net/package/amqp
注意事项:
- windows系统请点击 DLL
- linux下载后需要编译安装
- Windows下下载dll之前请检查php的相应版本,并下载对应的版本,否则会出现无法使用的问题
- Window下需要在php.ini下加入:
需要先将php_amqp.dll复制到php/ext目录下
[amqp]
extension=php_amqp.dll
然后在httpd.conf下加入:
需要先将rabbitmq.4.dll复制到配置目录下
# rabbitmq
LoadFile "d:/xampp/php/rabbitmq.4.dll"
这两个dll文件存在于下载的扩展中
- 一个关于RabbitMQ的php封装,此封装经过本人测试是可以使用的,但是有关信道和交换机这块因为本人仅仅是为了设置,所以在分配逻辑上做太多考虑,如果需要使用该方法可以在这方面做出相应的修改。
<?php
/**
* RabbitMQ消息队列封装
*/
namespace common\lib;
/**
* RabbitMQ消息队列生产者
*/
class RabbitMQ {
const HOST = '127.0.0.1';
const PORT = '5672';
const USER = 'zhangxugang810';
const PASSWORD = '132133';
const VHOST = 'huaweiQueue';
private $isTransaction = true;
private $exchangeName = 'ex_huawei';
private $queueName = 'queue_huawei';
private $routeKey = 'route_huawei';
private $cn;
private $ch;
private $ex;
private $queue;
public function __construct() {
$this->connect();
}
/**
* 组装参数
*/
private function connectParams() {
return ['host' => static::HOST, 'port' => static::PORT, 'login' => static::USER, 'password' => static::PASSWORD, 'vhost' => static::VHOST];
}
/**
* 连接队列服务器并创建channel
*/
private function connect() {
$params = $this->connectParams();
$this->cn = new \AMQPConnection($params);
if (!$this->cn->connect()) {
die("不能连接这个BROCKER\n");
}
$this->channel();
}
private function channel(){
$this->ch = new \AMQPChannel($this->cn);
}
/**
* 创建交换机
*/
private function exchange() {
$this->ex = new \AMQPExchange($this->ch);
$this->ex->setName($this->exchangeName);
date_default_timezone_set("Asia/Shanghai");
}
/**
* 创建队列并绑定交换机
*/
private function queue() {
//使用哪个信道
$this->queue = new \AMQPQueue($this->ch);
$this->queue->setName($this->queueName);
$this->queue->setFlags(AMQP_DURABLE);
// echo "Message Total:".$this->queue->declare()."\n";
// $this->queue->bind($this->exchangeName, $this->routeKey);
}
/**
* 生产者方法 - 单条
* @param type $msg
* @return type
*/
public function sendOne($msg){
$this->exchange();
return $this->ex->publish($msg, $this->routeKey);
}
/**
* 生产者方法 - 多条
* @param type $msgs
* @return type
*/
public function sendMultiple($msgs){
$this->exchange();
if ($this->isTransaction) {//如果启用事务
$this->ch->startTransaction(); //开始事务
}
$result = [];
foreach($msgs as $k => $msg){
$result[$k] = $this->ex->publish($msg, $this->routeKey);
}
if ($this->isTransaction) {//如果启用事务
$this->ch->commitTransaction(); //开始事务
}
return $result;
}
/**
* 消费者方法
* 这里需要根据相应的业务逻辑进行修改
*/
public function run() {
$this->queue();
echo "Message:\n";
while (True) {
$this->queue->consume(function($envelope, $queue) {
//此处调用业务逻辑处理方法
static::processMessage($envelope, $queue);
});
//$q->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
}
$this->disconnect();
}
/**
* 消费者业务逻辑
* 此处只是示例方法
* @param type $envelope
* @param type $queue
*/
public static function processMessage($envelope, $queue) {
//此处是业务逻辑处理
$msg = $envelope->getBody();
echo $msg . "\n"; //处理消息
$queue->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}
}
七、RabbitMQ单点问题与高可用
这里为了高可用性可以考虑一个问题,如果我们只部署一个单点RabbitMQ服务器用于生产环境,那么一但这个RabbitMQ出现问题,则所有调用该消息队列的应用都将出现问题,为了解决这个问题,就产生了RabbitMQ集群,具体的集群搭建,另做讲解。
八、踩坑提示
- windows安装时,请注意安装路径不要带空格
- 配置完成后直接运行程序,结果是队列消息无法加入,请检查所对应的虚拟主机是否存在,exchange是否存在,队列是否存在,exchange和队列是否绑定好了,如果未绑定成