MQ特点
编辑使用场景
编辑含义
编辑几个概念
编辑消息持久
编辑入门介绍
编辑基本概念
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
(2)客户端声明一个exchange,并设置相关属性。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routing key,在exchange和queue之间建立好绑定关系。
(5)客户端投递消息到exchange。
(1)exchange持久化,在声明时指定durable => 1
(2)queue持久化,在声明时指定durable => 1
(3)消息持久化,在投递时指定delivery_mode => 2(1是非持久化)
依赖包安装
yum install ncurses-devel unixODBC unixODBC-devel
erlang环境
wget http://erlang.org/download/otp_src_18.1.tar.gztar -zxvf otp_src_18.1.tar.gzcd otp_src_18.1./configure --prefix=/usr/local/erlangmakemake install# 配置erlang环境变量vim /etc/profile# 增加内容:export PATH="$PATH:/usr/local/erlang/bin"# 保存退出,并刷新变量source /etc/profile# 测试erlang是否安装成功# 安装完成以后,执行erl看是否能打开eshell,用’halt().’退出,注意后面的点号,那是erlang的结束符。[root@localhost src]# erl Erlang/OTP 17 [erts-6.1] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]Eshell V6.1 (abort with ^G) 2> 9+3. 12 3> halt().
安装rabbitmq依赖文件,安装rabbitmq
# 安装rabbitmq依赖包yum install xmlto# 安装rabbitmq服务端wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.5.7/rabbitmq-server-3.5.7.tar.gztar zxvf rabbitmq-server-3.5.7.tar.gzcd rabbitmq-server-3.5.7/makemake install TARGET_DIR=/usr/local/rabbitmq SBIN_DIR=/usr/local/rabbitmq/sbin MAN_DIR=/usr/local/rabbitmq/man DOC_INSTALL_DIR=/usr/local/rabbitmq/doc# 配置hostsvim /etc/hosts# 增加一行内容# 当前IP地址 绑定HOSTNAME名称(vim /etc/sysconfig/network)192.168.2.208 localhost.localdomain# 这种会提示错误(Warning: PID file not written; -detached was passed.)/usr/local/rabbitmq/sbin/rabbitmq-server -detached 启动rabbitmq/usr/local/rabbitmq/sbin/rabbitmqctl status 查看状态/usr/local/rabbitmq/sbin/rabbitmqctl stop 关闭rabbitmq# 目前我自己使用/usr/local/rabbitmq/sbin/rabbitmq-server start & 启动rabbitmq/usr/local/rabbitmq/sbin/rabbitmqctl status 查看状态/usr/local/rabbitmq/sbin/rabbitmqctl stop 关闭rabbitmq
启用管理插件
mkdir /etc/rabbitmq/usr/local/rabbitmq/sbin/rabbitmq-plugins list 查看插件列表/usr/local/rabbitmq/sbin/rabbitmq-plugins enable rabbitmq_management (启用插件)/usr/local/rabbitmq/sbin/rabbitmq-plugins disable rabbitmq_management (禁用插件)# 重启rabbitmq# 访问 http://127.0.0.1:15672/# 如果有iptablesvim /etc/sysconfig/iptables# 增加一下内容-A INPUT -m state --state NEW -m tcp -p tcp --dport 15672 -j ACCEPT# 重启动iptableservice iptables restart
开机自启动配置
#!/bin/sh#start rabbitMqsudo /usr/local/rabbitmq/sbin/rabbitmq-server & > /usr/local/rabbitmq/logs/rabbitmq.log 2>&1
RabbitMQ PHP扩展安装
# 安装rabbitmq-c依赖包yum install libtool autoconf# 安装rabbitmq-c ( 最好下载 0.5的,0.6安装可能会报错)# 版本下载:https://github.com/alanxz/rabbitmq-c/releases/tag/v0.5.0wget https://github.com/alanxz/rabbitmq-c/releases/download/v0.5.0/rabbitmq-c-0.5.0.tar.gztar -zxvf v0.5.0cd rabbitmq-c-0.5.0/autoreconf -i./configure --prefix=/usr/local/rabbitmq-cmakemake install# 安装PHP扩展 amqpwget http://pecl.php.net/get/amqp-1.6.1.tgztar zxvf amqp-1.6.1.tgzcd amqp-1.6.1/usr/local/php/bin/phpize./configure --with-php-config=/usr/local/php/bin/php-config --with-amqp --with-librabbitmq-dir=/usr/local/rabbitmq-cmakemake install# 编辑php.ini文件,增加amqp扩展支持vim /usr/local/php/etc/php.ini# 增加下面内容; rabbitmq扩展支持extension=amqp.so# 重启php-fpm/etc/init.d/php-fpm restart
验证是否成功 phpinfo()查看下是否支持amqp扩展
相关配置
hostname mq // 设置hostname名称vim /etc/sysconfig/network // 设置hostnamevim /etc/hosts // 编辑hosts./rabbitmqctl add_user admin admin // 添加用户./rabbitmqctl set_user_tags admin administrator // 添加admin 到 administrator分组./rabbitmqctl set_permissions -p / admin "*." "*." "*." // 添加权限
创建配置文件
#在/usr/rabbitmq/sbin/rabbitmq-defaults 查看config文件路径# 创建配置文件 touch/usr/rabbitmq/sbin#vm_memory_high_watermark 内存低水位线,若低于该水位线,则开启流控机制,阻止所有请求,默认值是0.4,即内存总量的40%,#vm_memory_high_watermark_paging_ratio 内存低水位线的多少百分比开始通过写入磁盘文件来释放内存vi /usr/rabbitmq/sbin/rabbitmq.config 输入[{rabbit, [{vm_memory_high_watermark_paging_ratio, 0.75}, {vm_memory_high_watermark, 0.7}]}].
创建环境文件
touch /etc/rabbitmq/rabbitmq-env.conf#输入 RABBITMQ_NODENAME=FZTEC-240088 节点名称 RABBITMQ_NODE_IP_ADDRESS=127.0.0.1 监听IP RABBITMQ_NODE_PORT=5672 监听端口 RABBITMQ_LOG_BASE=/data/rabbitmq/log 日志目录 RABBITMQ_PLUGINS_DIR=/data/rabbitmq/plugins 插件目录 RABBITMQ_MNESIA_BASE=/data/rabbitmq/mnesia 后端存储目录
操作命令
查看exchange信息 /usr/rabbitmq/sbin/rabbitmqctl list_exchanges name type durable auto_delete arguments 查看队列信息 /usr/rabbitmq/sbin/rabbitmqctl list_queues name durable auto_delete messages consumers me 查看绑定信息 /usr/rabbitmq/sbin/rabbitmqctl list_bindings 查看连接信息 /usr/rabbitmq/sbin/rabbitmqctl list_connections
php的server端脚本
<?php
$routingkey='key';
//设置你的连接
$conn_args = array('host' => 'localhost', 'port' => '5672', 'login' => 'guest', 'password' => 'guest');
$conn = new AMQPConnection($conn_args);
if ($conn->connect()) {
echo "Established a connection to the broker \n";
}
else {
echo "Cannot connect to the broker \n ";
}
//你的消息
$message = json_encode(array('Hello World3!','php3','c++3:'));
//创建channel
$channel = new AMQPChannel($conn);
//创建exchange
$ex = new AMQPExchange($channel);
$ex->setName('exchange');//创建名字
$ex->setType(AMQP_EX_TYPE_DIRECT);
$ex->setFlags(AMQP_DURABLE);
//$ex->setFlags(AMQP_AUTODELETE);
//echo "exchange status:".$ex->declare();
echo "exchange status:".$ex->declareExchange();
echo "\n";
for($i=0;$i<100;$i++){
if($routingkey=='key2'){
$routingkey='key';
}else{
$routingkey='key2';
}
$ex->publish($message,$routingkey);
}
/*
$ex->publish($message,$routingkey);
创建队列
$q = new AMQPQueue($channel);
设置队列名字 如果不存在则添加
$q->setName('queue');
$q->setFlags(AMQP_DURABLE | AMQP_AUTODELETE);
echo "queue status: ".$q->declare();
echo "\n";
echo 'queue bind: '.$q->bind('exchange','route.key');
将你的队列绑定到routingKey
echo "\n";
$channel->startTransaction();
echo "send: ".$ex->publish($message, 'route.key'); //将你的消息通过制定routingKey发送
$channel->commitTransaction();
$conn->disconnect();
*/
php客户端脚本
<?php
$bindingkey='key2';
//连接RabbitMQ
$conn_args = array( 'host'=>'127.0.0.1' , 'port'=> '5672', 'login'=>'guest' , 'password'=> 'guest','vhost' =>'/');
$conn = new AMQPConnection($conn_args);
$conn->connect();
//设置queue名称,使用exchange,绑定routingkey
$channel = new AMQPChannel($conn);
$q = new AMQPQueue($channel);
$q->setName('queue2');
$q->setFlags(AMQP_DURABLE);
$q->declare();
$q->bind('exchange',$bindingkey);
//消息获取
$messages = $q->get(AMQP_AUTOACK) ;
if ($messages){
var_dump(json_decode($messages->getBody(), true ));
}
$conn->disconnect();
?>
今天用一个简单的案例来实现 RabbitMQ + PHP 这个消息队列的运行机制。
主要分为两个部分:
第一:发送者(publisher)
第二:消费者(consumer)
(一)生产者 (创建一个rabbit_publisher.php的文件)
$conn_args = array(
'host' => '127.0.0.1',
'port' => '5672',
'login' => 'guest',
'password' => 'guest',
'vhost'=>'/'
);
//创建连接和channel
$conn = new AMQPConnection($conn_args);
if (!$conn->connect()) {
die("Cannot connect to the broker!\n");
}
$channel = new AMQPChannel($conn);
//创建交换机
$e_name = 'e_linvo'; //交换机名
$ex = new AMQPExchange($channel);
$ex->setName($e_name);
$ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型
$ex->setFlags(AMQP_DURABLE); //持久化
echo "Exchange Status:".$ex->declare()."\n";
echo "Send Message:".$ex->publish("TEST MESSAGE,key_1 by xust" . date('H:i:s', time()), 'key_1')."\n";
echo "Send Message:".$ex->publish("TEST MESSAGE,key_2 by xust" . date('H:i:s', time()), 'key_2')."\n";
(二)消费者(创建一个rabbit_consumer.php的文件)
创建连接-->创建channel-->创建交换机-->创建队列-->绑定交换机/队列/路由键-->接收消息
$conn_args = array(
'host' => '127.0.0.1',
'port' => '5672',
'login' => 'guest',
'password' => 'guest',
'vhost'=>'/'
);
$e_name = 'e_linvo'; //交换机名
$q_name = 'q_linvo'; //队列名
$k_route = 'key_2'; //路由key
//创建连接和channel
$conn = new AMQPConnection($conn_args);
if (!$conn->connect()) {
die("Cannot connect to the broker!\n");
}
$channel = new AMQPChannel($conn);
//创建交换机
$ex = new AMQPExchange($channel);
$ex->setName($e_name);
$ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型
$ex->setFlags(AMQP_DURABLE); //持久化
echo "Exchange Status:".$ex->declare()."\n";
//创建队列
$q = new AMQPQueue($channel);
$q->setName($q_name);
$q->setFlags(AMQP_DURABLE); //持久化
//绑定交换机与队列,并指定路由键
echo 'Queue Bind: '.$q->bind($e_name, 'key_2')."\n";
//阻塞模式接收消息
echo "Message:\n";
$q->consume('processMessage', AMQP_AUTOACK); //自动ACK应答
$conn->disconnect();
/**
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $queue) {
var_dump($envelope->getRoutingKey);
$msg = $envelope->getBody();
echo $msg."\n"; //处理消息
}