消息中间件RabbitMQ
ubuntu下安装:
先安装erlang,因为rabbitmq是基于erlang开发的
$ sudo apt-get update
$ sudo apt-get install erlang
完成后控制台输入erl 如下图显示说明安装成功
再安装rabbitmq
sudo apt-get install rabbitmq-server
使用:
先用rabbitmq发送个helloworld
P为生产者,即主动发送消息;C为消费者,即接受消息。中间的为传输队列。
发送者 send.py 的实现:
建立连接:
import pika
# 建立连接
# 中间件和发送者在同一台机器,则host为localhsot。host为安装了rabbitmq的机器的ip
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
创建接受消息的队列:
channel.queue_declare(queue='hello') # 创建一个名为hello的队列
此时send.py已做好了发送的准备,要将 字符串"hello world"发送到名字为“hello”的队列。
但消息不能直接发送到队列,需要通过exchange(交换器),先用默认的exchange,稍后再将exchange是什么。
channel.basic_publish(exchange='', #空串,定义默认的exchange
routing_key='hello', # 队列名称需要routing_key指定
body='Hello World!') # 需要发送的内容'Hello World!'
print(" [x] Sent 'Hello World!'")
在退出程序之前,通过close()可以确保网络缓冲区已刷新,并且我们的消息已传递到rabbitmq。
connection.close()
生产者 send.py 完整的代码:
import pika
# 建立连接
# 中间件和发送者在同一台机器,则host为localhsot
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello') # 创建一个名为hello的队列
channel.basic_publish(exchange='', #空串,定义默认的exchange
routing_key='hello', # 队列名称需要routing_key指定
body='Hello World!') # 需要发送的内容'Hello World!'
print(" [x] Sent 'Hello World!'")
connection.close() # 关闭连接
此时生产者,即发送者写好了,开始写消费者 receive.py 同样先连接上:
import pika
# 建立连接
# 中间件和接受在同一台机器,则host为localhsot
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
声明一个队列,从这个队列接受数据
channel.queue_declare(queue='hello') #建立队列,名字为‘hello’
之前在生产者中已经声明了一个队列‘hello’,消费者怎么又声明一次呢?这是因为我们不确定生产者和消费者哪个程序先运行,为了保证队列一定存在,所以在两个程序中都声明了名为‘hello’的队列。
放心,channel.queue_declare(queue=‘hello’)这句话不管执行多少次,都会只生成一个名为‘hello’的队列。
当消费者接受消息时,触发回调函数,打印出接受到的消息
# 回调函数
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback, # 指明回调函数
queue='hello', # 指明队列为‘hello’
no_ack=True) # no_ack=True是接收到消息后不用给生产者发确认消息
开始无限循环的接受消息,并随时调用callback处理消息
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
消费者 receive.py 的完整代码:
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
channel.basic_consume(callback,
queue='hello',
no_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
启动两个程序后,消费者一直等待消息的到来,程序 receive.py 不会停止。
如果rabbitmq服务没有启动,则会报错误 :
“由于目标计算机积极拒绝,无法连接。”
所以首先要保证rabbitmq服务已启动,rabbitmq的安装我就不说了。
本来到这里发送‘helloworld’就结束了,但这个例子是生产者和消费者和rabbitmq在同一台机子上。下面说一下远程连接。
我的rabbitmq安装在A机器上,生产者 send.py 也在A机器上,所以生产者连接rabbitmq时,host为localhost。即
connection = pika.BlockingConnection(pika.ConnectionParameters(host=‘localhost’))
但消费者 receive.py 在B机器上,所以消费者连接时, host=A机器的ip,即
connection = pika.BlockingConnection(pika.ConnectionParameters(host=‘A的ip地址’))
此时运行B上的消费者 receive.py 时会报错:
“ pika.exceptions.ProbableAuthenticationError: (403, ‘ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.’) ”
因为远程连接时要为rabbitmq建立一个用户,然后用用户名和密码来远程连接,所以B机上的消费者 receive.py在连接rabbitmq时的代码为
username = 'username' #指定远程rabbitmq的用户名
pwd = 'password' #指定远程rabbitmq的密码
user_pwd = pika.PlainCredentials(username, pwd)
connection = pika.BlockingConnection(pika.ConnectionParameters(host='192.168.2.174', credentials=user_pwd))
channel = connection.channel()
下面说一下在怎么配置这个用户名,在安装有rabbitmq的电脑上
rabbitmqctl list_users //查看所有用户
rabbitmqctl add_user username password //新建用户并设置密码
rabbitmqctl set_user_tags username administrator //新建用户配置为administrator的角色,超级管理员
rabbitmqctl set_permissions -p / username ‘.*’ ‘.*’ ‘.*’ //为新建用户配置权限
此时就可以用这个用户来远程访问了。
其他常用命令:
service rabbitmq-server status 查看状态
rabbitmq-server start & 后台启动rabbitmq
rabbitmq-plugins list 查看rabbitmq插件
sudo rabbitmq-plugins enable rabbitmq_management 启动管控台,页面端口为15672