选择RPM包下载,选择对应平台,本次安装在CentOS7,其他平台类似。https://www.rabbitmq.com/install-rpm.html
由于使用了erlang语言开发,所以需要erlang的包。erlang和RabbitMQ的兼容性,参考https://www.rabbitmq.com/which-erlang.html#compatibility-matrix
第二种错误,可以修改host文件,修改主机名即可
下载 rabbitmq-server-3.7.16-1.el7.noarch.rpm、erlang-21.3.8.6-1.el7.x86_64.rpm。socat在CentOS中源中有。
yum -y install erlang-21.3.8.6-1.el7.x86_64.rpm rabbitmq-server-3.7.16-1.el7.noarch.rpm
[root@xdd ~]# rpm -ql rabbitmq-server
/etc/logrotate.d/rabbitmq-server
/etc/profile.d/rabbitmqctl-autocomplete.sh
/etc/rabbitmq
/usr/lib/ocf/resource.d/rabbitmq/rabbitmq-server
/usr/lib/ocf/resource.d/rabbitmq/rabbitmq-server-ha
/usr/lib/rabbitmq/autocomplete/bash_autocomplete.sh
/usr/lib/rabbitmq/autocomplete/zsh_autocomplete.sh
/usr/lib/rabbitmq/bin/cuttlefish
/usr/lib/rabbitmq/bin/rabbitmq-defaults
RABBITMQ_NODE_IP_ADDRESS the empty string, meaning that it should bind to all network interfaces.
RABBITMQ_NODE_PORT 5672
RABBITMQ_DIST_PORT RABBITMQ_NODE_PORT + 20000 #内部节点和客户端工具通信用
RABBITMQ_CONFIG_FILE 配置文件路径默认为/etc/rabbitmq/rabbitmq
环境变量文件,可以不配置
2. sysctl格式,如果不需要兼容,RabbitMQ鼓励使用。 (这个文件也可以不配置)
列出所有可用插件
rabbitmq-plugins list
[root@xdd rabbitmq]$ rabbitmq-plugins enable rabbitmq_management
systemctl start rabbitmq-server
Error when reading /var/lib/rabbitmq/.erlang.cookie:eacces
这就是这个文件的权限问题,修改属组、属组为rabbitmq即可chown rabbitmq.rabbitmq /var/lib/rabbitmq/.erlang.cookie
[root@xdd ~]# ss -tanl | grep 5672
LISTEN 0 128 *:25672 *:*
LISTEN 0 128 *:15672 *:*
LISTEN 0 128 :::5672 :::*
[root@xdd ~]#
rabbitmqctl [-n ] [-1][-q] []
-n
node-q
,–quiet-t
,–timeout timeout-l
longnamesadd_user
添加用户list_user
列出用户delete_user username
删除用户change_password
修改用户名,密码set_user_tags [...]
设置用户tag添加用户:rabbitmqctl add_user username password
删除用户:rabbitmqctl delete_user username
更改密码:rabbitmqctl change_password username newpassword
设置权限Tags,其实就是分配组:rabbitmqctl set_user_tags username tag
设置xdd用户为管理员tag后登陆
# rabbitmqctl add_user gdy gdy #添加xdd用户
# rabbitmqctl list_users #查看所有用户
# rabbitmqctl set_user_tags gdy administrator #设置xdd用户为管理员用户
tag的意义如下:
虚拟主机
pip install pika
名词 | 说明 |
---|---|
Server | 服务器 接受客户端连接,实现消息队列及路由功能的进程(服务),也称为消息代理 注意:客户端可用生产者,也可以是消费者,它们都需要连接到Server |
Connection | 网络物理连接 |
Channel | 一个连接允许多个客户端连接 |
Exchange | 交换器。接收生产者发来的消息,决定如何路由给服务器中的队列。 常用的类型有: direct(point-to-point) topic(publish-subscribe) fanout(multicast) |
Message | 消息 |
Message Queue | 消息队列,数据的存储载体 |
Bind | 绑定 建立消息队列和交换器之间的关系,也就是说交换器拿到数据,把什么样的数据送给哪个队列 |
Virtual Host | 虚拟主机 一批交换器、消息队列和相关对象的集合。为了多用户互不干扰,使用虚拟主机分组交换机,消息队列 |
Topic | 主题、话题 |
Broker | 可等价为Server |
pika.exceptions.ProbableAuthenticationError: (403, 'ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.')
在ConnectionParameters中没有用户名、密码填写的参数,它使用参数credentials传入,这个需要构建一个pika.credentials.Credentials对象。
参照官方例子,写一个小程序
# send.py
import pika
from pika.adapters.blocking_connection import BlockingChannel
#构建用户名密码对象
credential = pika.PlainCredentials("gdy","gdy")
# 配置链接参数
params = pika.ConnectionParameters(
"192.168.61.108",#ip地址
5672, #端口
"test",#虚拟机
credential #用户名密码
)
# # 第二种建立连接方式
# params = pika.URLParameters("amqp://gdy:[email protected]:5672/test")
# 建立连接
connection = pika.BlockingConnection(params)
with connection:
# 建立通道
channel:BlockingChannel = connection.channel()
#创建一个队列,queue命名为hello,如果queue不存在,消息将被dropped
channel.queue_declare(queue="hello")
channel.basic_publish(
exchange="",#使用缺省exchange
routing_key="hello", #routing_key必须指定,这里要求和目标queue一致
body="Hello world" #消息
)
print("消息发送成功Sent Message OK")
# amqp://username:password@host:port/[?query-string]
parameters = pika.URLParameters('amqp://guest:guest@rabbit-server1:5672/%2F')
# %2F指代/,就是缺省虚拟主机
# send.py
import pika
from pika.adapters.blocking_connection import BlockingChannel
import time
# 第二种建立连接方式
params = pika.URLParameters("amqp://gdy:[email protected]:5672/test")
# 建立连接
connection = pika.BlockingConnection(params)
with connection:
# 建立通道
channel:BlockingChannel = connection.channel()
#创建一个队列,queue命名为hello,如果queue不存在,消息将被dropped
channel.queue_declare(queue="hello")
for i in range(40):
channel.basic_publish(
exchange="",#使用缺省exchange
routing_key="hello", #routing_key必须指定,这里要求和目标queue一致
body="data{:02}".format(i) #消息
)
time.sleep(0.5)
print("消息发送成功Sent Message OK")
# receie.py
import pika
from pika.adapters.blocking_connection import BlockingChannel
# 建立连接
params = pika.URLParameters("amqp://gdy:[email protected]:5672/test")
connection = pika.BlockingConnection(params)
with connection:
channel:BlockingChannel = connection.channel()
msg = channel.basic_get("hello",True) #从名称为hello的queue队列中获取消息,获取不到阻塞
method,props,body = msg #拿不到的消息tuple为(None,None,None)
if body:
print("获取到了一个消息Get A message = {}".format(body))
else:
print("没有获取到消息empty")
(, , b'data01')
返回元组:(方法method,属性properties,消息body)
无数据返回:(None,None,None)
# receie.py 消费代码
import pika
from pika.adapters.blocking_connection import BlockingChannel
# 建立连接
params = pika.URLParameters("amqp://gdy:[email protected]:5672/test")
connection = pika.BlockingConnection(params)
def callback(channel,method,properties,body):
print("Get a message = {}".format(body))
with connection:
channel:BlockingChannel = connection.channel()
channel.basic_consume(
"hello",#队列名
callback,#消费回调函数
True,#不回应
)
print("等待消息,退出按CTRL+C;Waiting for messages. To exit press CTRL+C")
channel.start_consuming()
# 生成一个交换机
channel.exchange_declare(
exchange="logs", #新交换机
exchange_type="fanout" #广播
)
# 消费者端
result =channel.queue_declare(queue="") #生成一个随机名称的queue
resutl = channel.queue_declare(queue="",exclusive=True) #生成一个随机名称的queue,并在断开链接时删除queue
# 生成queue
q1:Method = channel.queue_declare(queue="",exclusive=True)
q2:Method = channel.queue_declare(queue="",exclusive=True)
q1name = q1.method.queue #可以通过result.method.queue 查看随机名称
q2name = q2.method.queue
print(q1name,q2name)
#绑定
channel.queue_bind(exchange="logs",queue=q1name)
channel.queue_bind(exchange="logs",queue=q2name)
# send.py 生产者代码
import pika
from pika.adapters.blocking_connection import BlockingChannel
import time
# 建立连接
params = pika.URLParameters("amqp://gdy:[email protected]:5672/test")
connection = pika.BlockingConnection(params)
channel:BlockingChannel = connection.channel()
with connection:
#指定交换机和模式
channel.exchange_declare(
exchange="logs",#新交换机
exchange_type="fanout" #扇出,广播
)
for i in range(40):
channel.basic_publish(
exchange="logs",#使用指定的exhcange
routing_key="", #广播模式,不指定routing_key
body = "data-{:02}".format(i) #消息
)
time.sleep(0.01)
print("消息发送完成")
# receie.py 消费者代码
import time
import pika
from pika.adapters.blocking_connection import BlockingConnection
from pika.adapters.blocking_connection import BlockingChannel
connection:BlockingConnection = pika.BlockingConnection(pika.URLParameters("amqp://gdy:[email protected]:5672/test"))
channel:BlockingChannel = connection.channel()
# 指定交换机
channel.exchange_declare(exchange="logs",exchange_type="fanout")
q1 = channel.queue_declare(queue="",exclusive=True)
q2 = channel.queue_declare(queue="",exclusive=True)
name1 = q1.method.queue #队列名
name2 = q2.method.queue
#为交换机绑定queue
channel.queue_bind(exchange="logs",queue=name1)
channel.queue_bind(exchange="logs",queue=name2)
def callback(channel,method,properties,body):
print("{}\n{}".format(channel,method))
print("获取了一个消息 Get a message = {}".format(body))
with connection:
#为第一个队列绑定消费者函数
channel.basic_consume(
name1,#队列名
callback, #消费者回调函数
True #不回应
)
#为第二个队列绑定消费者函数
channel.basic_consume(name2,callback,True)
print("等待消息,退出按CTRL+C;Waiting for messages. To exit press CTRL+C")
channel.start_consuming()
q1 = channel.queue_declare(queue="",exclusive=True)
q2 = channel.queue_declare(queue="",exclusive=True)
# send生产者
import time
import pika
import random
from pika.adapters.blocking_connection import BlockingConnection
from pika.adapters.blocking_connection import BlockingChannel
exchangename = "color"
colors = ("orange","black","green")
#建立连接
connection:BlockingConnection = pika.BlockingConnection(pika.URLParameters("amqp://gdy:[email protected]:5672/test"))
channel:BlockingChannel = connection.channel()
with connection:
channel.exchange_declare(
exchange=exchangename,#使用指定的exchange
exchange_type="direct" #路由模式
)
for i in range(40):
rk = random.choice(colors)
msg = "{}-data-{:02}".format(rk,i)
channel.basic_publish(
exchange=exchangename,#
routing_key=rk,#指定routing_key
body=msg #消息
)
print(msg,"----")
time.sleep(0.01)
print("消息发送完成 Sent ok")
# receie.py消费者
import time
import pika
import random
from pika.adapters.blocking_connection import BlockingConnection
from pika.adapters.blocking_connection import BlockingChannel
exchangename = "color"
colors = ("orange","black","green")
#建立连接
connection:BlockingConnection = pika.BlockingConnection(pika.URLParameters("amqp://gdy:[email protected]:5672/test"))
channel:BlockingChannel = connection.channel()
channel.exchange_declare(exchange=exchangename,exchange_type="direct")
# 生成队列,名称随机,exclusive=True断开删除该队列
q1 = channel.queue_declare(queue="",exclusive=True)
q2 = channel.queue_declare(queue="",exclusive=True)
name1 = q1.method.queue #查看队列名
name2 = q2.method.queue
print(name1,name2)
#绑定到交换机,而且一定要绑定routing_key
channel.queue_bind(exchange=exchangename,queue=name1,routing_key=colors[0])
channel.queue_bind(exchange=exchangename,queue=name2,routing_key=colors[1])
channel.queue_bind(exchange=exchangename,queue=name2,routing_key=colors[2])
def callback(channel,method,properties,body):
print("{}\n{}".format(channel,method))
print("获取了一个消息get a message = {}".format(body))
print()
with connection:
channel.basic_consume(
name1,#队列名
callback, #消息回调函数
True #不回应
)
channel.basic_consume(name2,callback,True)
print("等待消息,退出按CTRL+C;Waiting for messages. To exit press CTRL+C")
channel.start_consuming()
注意:如果routing_key设置一样,绑定的时候指定routing_key=‘black’,如下图。和fanout就类似了,都是1对多,但是不同。
.
点号分割的单词组成。最多255个字节。*
表示严格的一个单词#
表示0个或多个单词#
,这个queue其实可以接收所有的消息。# send.py生产者代码
import time
import pika
import random
from pika.adapters.blocking_connection import BlockingConnection
from pika.adapters.blocking_connection import BlockingChannel
exchangename = "products"
#产品和颜色搭配
colors = ("orange","black","green")
topics = ("phone.*","*.red") #两种话题
product_type = ("phone","pc","tv") #3种产品
#建立连接
connection:BlockingConnection = pika.BlockingConnection(pika.URLParameters("amqp://gdy:[email protected]:5672/test"))
channel:BlockingChannel = connection.channel()
#指定交换机为话题模式
channel.exchange_declare(exchange=exchangename,exchange_type="topic")
with connection:
for i in range(40):
rk = "{}.{}".format(random.choice(product_type),random.choice(colors))
msg = "{}-data-{:02}".format(rk,i)
channel.basic_publish(
exchange=exchangename,#使用指定的exchange
routing_key=rk,#指定routing_key
body=msg #消息
)
print(msg,"-----")
time.sleep(0.5)
print("消息发送完成 Sent ok")
# recieve.py 消费者代码
import time
import pika
import random
from pika.adapters.blocking_connection import BlockingConnection
from pika.adapters.blocking_connection import BlockingChannel
# 虚拟机名称
exchangename = "products"
#建立连接
connection:BlockingConnection = pika.BlockingConnection(pika.URLParameters("amqp://gdy:[email protected]:5672/test"))
channel:BlockingChannel = connection.channel()
#指定虚拟机,交换机为话题模式
channel.exchange_declare(exchange=exchangename,exchange_type="topic")
# 生成队列,名称随机,exclusive=True断开删除该队列
q1 = channel.queue_declare(queue="",exclusive=True)
q2 = channel.queue_declare(queue="",exclusive=True)
name1 = q1.method.queue #查看队列名
name2 = q2.method.queue
print(name1,name2)
#绑定到交换机,而且一定绑定routing_key
#q1只收集phone开头的routing_key的消息,也就是说只管收集类型信息
channel.queue_bind(exchange=exchangename,queue=name1,routing_key="phone.*")
# q2只收集red结尾的routing_key的消息,也就是说只管红色的信息
channel.queue_bind(exchange=exchangename,queue=name2,routing_key="*.red")
def callback(channel,method,properties,body):
print("{}\n{}".format(channel,method))
print("获取了一个消息Get a message = {}".format(body))
print()
with connection:
channel.basic_consume(
name1,#队列名
callback,#消息回调函数
True #不回应
)
channel.basic_consume(name2,callback,True)
print("等待消息,退出按CTRL+C;Waiting for messages. To exit press CTRL+C")
channel.start_consuming()