环境:centos7
Centos7上面安装rabbitmq工具
1、安装erlang:yum install -y epel-release erlang
2、查看版本:erl -version
3、下载rabbitmq-server并进行yum安装,官网:http://www.rabbitmq.com/download.html
(3-1)cd到src目录:cd /usr/src
(3-2)下载最新的:
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.8/rabbitmq-server-3.9.8-1.el7.noarch.rpm
(3-3)然后执行:rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
(3-4)安装:yum install -y rabbitmq-server
(3-5)启动
开机自启动:chkconfig rabbitmq-server on
启动服务:service rabbitmq-server start
查看服务状态:service rabbitmq-server status
(3-6)安装web管理工具:rabbitmq-plugins enable rabbitmq_management
4.安装完成,默认账号:guest,密码 :guest,添加可以远程登陆的账号
sudo rabbitmqctl add_user test 123456
sudo rabbitmqctl set_user_tags test administrator
sudo rabbitmqctl set_permissions -p / test “." ".” “.*”
浏览器访问:服务器ip+端口15672
访问不了则需要设置防火墙,开启15672端口,(直接关闭防火墙不行),操作参考如下(参考(4-1)开放端口即可):
(4-1)开放端口
firewall-cmd --zone=public --add-port=15672/tcp --permanent #开放15672端口
firewall-cmd --zone=public --remove-port=15672/tcp --permanent #关闭15672端口
firewall-cmd --reload #配置立即生效
(4-2)查看防火墙所有开放的端口:firewall-cmd --zone=public --list-ports
(4-3)关闭防火墙:systemctl stop firewalld.service ,如果要开放的端口太多,嫌麻烦,可以关闭防火墙,安全性自行评估
(4-4)查看防火墙状态:firewall-cmd --state
(4-5)查看监听的端口:netstat -lnpt
PS:centos7默认没有 netstat 命令,需要安装 net-tools 工具,yum install -y net-tools
(4-6)检查端口被哪个进程占用:netstat -lnpt |grep 5672
(4-7)查看进程的详细信息:ps 6832
(4-8)中止进程:kill -9 6832
5.以上操作成功后,在服务器项目中使用composer安装:php-amqplib/php-amqplib
命令:composer require php-amqplib/php-amqplib
安装过程遇到的问题
(5-1)如果有提示让运行带上–no-plugins的,有的话执行下面第一个操作先看看
使用:composer selfupdate --no-plugins
(5-2)如果有还有其他的提示,试试以下操作
先删除tp框架中的:composer.lock文件
清除缓存:composer clearcache
更新:composer update 或者 composer self-update
生产者和消费者之间的逻辑代码:
项目config文件夹下新增配置文件rabbitmq.php
[
'host' => '192.168.2.198', //队列服务器ip
'port' => '5672', //默认端口
'login' => 'root', //账号,步骤4中添加
'password' => '123456', //密码
'vhost' => '/'
],
# 邮件队列
'email_queue' => [
'exchange_name' => 'email_exchange',
'exchange_type' => 'direct', #直连模式
'queue_name' => 'email_queue',
'route_key' => 'email_roteking',
'consumer_tag' => 'consumer'
]
];
生产者:
channel();
/*
name: $queue 创建队列
passive: false
持久durable: true // //队列将在服务器重启后继续存在
互斥exclusive: false // 队列可以通过其他渠道访问
auto_delete: false 通道关闭后,队列不会被删除
*/
$channel->queue_declare($amqpDetail['queue_name'], false, true, false, false);
/*
name: $exchange 创建交换机
type: direct 直连方式
passive: false
durable: true 持久// 交换器将在服务器重启后继续存在
auto_delete: false //一旦通道关闭,交换器将不会被删除。
*/
$channel->exchange_declare($amqpDetail['exchange_name'], 'direct', false, true, false);
/*
$messageBody:消息体
content_type:消息的类型 可以不指定
delivery_mode:消息持久化最关键的参数
AMQPMessage::DELIVERY_MODE_NON_PERSISTENT = 1;
AMQPMessage::DELIVERY_MODE_PERSISTENT = 2;
*/
$messageBody = $data;
$message = new AMQPMessage($messageBody, array('content_type' => 'text/plain', 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
$channel->basic_publish($message, $amqpDetail['exchange_name'],$amqpDetail['route_key']);
$channel->close();
$connection->close();
echo "ok";
}
}
消费者:
close();
$connection->close();
Log::write("closed",3);
}
function process_message($message)
{
echo $message->body."\n";
//手动发送ack
$message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']);
// 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']);
}
}
/**
* 启动
* @return \think\Response
*/
public function start()
{
$param = config('rabbitmq.AMQP');
$amqpDetail = config('rabbitmq.email_queue');
$connection = new AMQPStreamConnection(
$param['host'],
$param['port'],
$param['login'],
$param['password'],
$param['vhost']
);
$channel = $connection->channel();
$channel->queue_declare($amqpDetail['queue_name'], false, true, false, false);
$channel->exchange_declare($amqpDetail['exchange_name'], 'direct', false, true, false);
$channel->queue_bind($amqpDetail['queue_name'], $amqpDetail['exchange_name'],$amqpDetail['route_key']);
/*
queue: 从哪里获取消息的队列
consumer_tag: 消费者标识符
no_local: 不接收此使用者发布的消息
no_ack: 如果求设置为true,则此使用者将使用自动确认模式。详情请参见.
exclusive:请独占使用者访问,这意味着只有这个使用者可以访问队列
nowait:
callback: :PHP回调 array($this, 'process_message') 调用本对象的process_message方法
*/
$channel->basic_consume($amqpDetail['queue_name'], $amqpDetail['consumer_tag'], false, false, false, false, array($this, 'process_message'));
register_shutdown_function(array($this, 'shutdown'), $channel, $connection);
$count = count($channel->callbacks);
while ($count) {
$channel->wait();
}
}
}
完成生产者和消费者的两个类,下面我们把我们先自定义一个命令行,然后用这个命令:php think make:command Consumer行执行我们的消费者去消费消息生成命令行,然后稍作修改
执行完成后,在application目录下面会自动生成一个command目录,打开里面的Consumer.php文件,修改参考下面内容
protected function configure()
{
// 指令配置
$this->setName('consumer')->setDescription('php think consumer');
}
protected function execute(Input $input, Output $output)
{
$consumer = new Consumer();
// 指令输出
$consumer->start();
}
另外:tp6和tp5.1config目录下面的console.php文件内容各不相同
tp6:添加如下内容,注意如果在linux系统里,app\Command\Consumer,会提示找不到,有大小写区分(tp5.1忽略此项)
[
// consumer是app\Command\Consumer文件中自定义命令行的名字
'consumer' => 'app\Command\Consumer'
],
];
tp5.1:是自带的默认内容,不需要修改
'Think Console',
'version' => '0.1',
'user' => null,
'auto_path' => env('app_path') . 'command' . DIRECTORY_SEPARATOR,
];
然后在项目中使用命令:php think consumer ,将消费者端运行挂起
完成上述内容后,写一个接口,模拟用户访问:
pushMessage('time:'.time().' Look at the girl opposite ');
}
}
然后访问浏览器或者postman访问send:http://127.0.0.1/service/MqService/send
此时就会看到挂起消费端的控制台,会输出“Look at the girl opposite”,则表示生产者发出的消息,消费者已经将其消费掉了
如果关掉消费端的挂起,再次访问send方法,在浏览器访问:服务器ip+端口15672的页面列,队列项中就会看到未被消费的消息
参考:https://blog.csdn.net/qq_39077464/article/details/108993831