rabbitmq-server官方文档:https://www.rabbitmq.com/tutorials/tutorial-one-python.html
pika Python client 官方异常错误文档:http://pika.readthedocs.io/en/latest/modules/exceptions.html
一、
首先,这篇文档的开端,得益于链接:http://blog.csdn.net/fgf00/article/details/52872730博主的文档的启蒙
RabbitMQ是消息队列,【Disk、Socket、其他中间件】这里中间件不仅可以支持两个程序之间交互,可以支持多个程序,可以维护好多个程序的队列。
像这种公共的中间件有好多成熟的产品:
RabbitMQ
ZeroMQ
ActiveMQ
……
RabbitMQ:erlang语言 开发的。
Python中连接RabbitMQ的模块:pika 、Celery(分布式任务队列) 、haigha
可以维护很多的队列
RabbitMQ 教程官网:http://www.rabbitmq.com/getstarted.html
几个概念说明:
Broker:简单来说就是消息队列服务器实体。
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
RabbitMQ原理介绍:
RabbitMQ 是一个消息代理。它的核心原理非常简单:接收和发送消息。你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处。在这个比喻中,RabbitMQ就扮演着邮箱、邮局以及邮递员的角色。
RabbitMQ 和邮局的主要区别是,它不是用来处理纸张的,它是用来接收、存储和发送消息(message)这种二进制数据的。
在这里我们使用生产者、消费者模型来进行此次的模拟。
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
需要指出的是生产者、消费者、代理一般不会放置在在同一个设备上;事实上大多数应用也确实不在会将他们放在一台机器上。
二、
rabbitmq-server安装:
sudo apt-get install rabbitmq-server
管理服务器:
启动:sudo service rabbitmq-server start
关闭: sudo service rabbitmq-server stop
查看状态:sudo service rabbitmq-server status
控制系统限制:
如果要调整系统限制(尤其是打开文件的句柄的数量)的话,可以通过编辑 /etc/default/rabbitmq-server 文件让服务启动的时候调用ulimit,例如:
# 这将会设置此服务打开文件句柄的最大数量为1024个(这也是默认设置)。
ulimit -n 1024
pika的安装:
sudo apt-get install python-pip git-core # 安装所需要的依赖
sudo pip install pika==0.9.5
(注意:引起下面程序出错的原因,我在这之前将guest用户删除了,自己添加了个admin用户。)
Python实现hello world的发送---->中间件rabbitmq---->接收
代码如下:
producer.py(发送者、生产者)
#在 RabbitMQ 中,消息是不能直接发送到队列,它需要发送到交换机(exchange)中,它使用一个空字符串来标识。交换机允许我们指定某条消息需要投递到哪个队列。 routing_key 参数必须指定为队列的名称:
import pika
'''
建立连接
'''
connection=pika.BlockingConnection(pika.ConnectionParameters('localhost',5672));
channel=connection.channel();
channel.queue_declare(queue='hello');#创建了一个消息队列
channel.basic_publish(exchange='',routing_key='hello',body='Hello World');#默认交换机、队列名、消息内容
print("[x]sent 'Hello World!");
connection.close();#确保网络缓冲区被刷新,并且我们的消息实际上传递给RabbitMQ
consumer.py(接收者,消费者)
import pika
import time
#creds_broker=pika.PlainCredentials("admin","admin")
connection=pika.BlockingConnection(pika.ConnectionParameters('localhost'));
channel=connection.channel();
channel.queue_declare(queue='hello');#使用queue_declare创建一个队列——我们可以运行这个命令很多次,但是只有一个队列会被创建。
def callback(ch,method,properties,body):#从队列中获取消息相对来说稍显复杂。需要为队列定义一个回调(callback)函数。当我们获取到消息的时候,Pika 库就会调用此回调函数。这个回调函数会将接收到的消息内容输出到屏幕上。
print(ch,method,properties);
print("[x] Received %r"%body);
time.sleep(15);
ch.basic_ack(delivery_tag=method.delivery_tag);
channel.basic_consume(callback,queue='hello');#我们需要告诉 RabbitMQ 这个回调函数将会从名为 "hello" 的队列中接收消息:
print('[x]Waiting for messages.To exit press CTRL+C');#最后,我们输出一个用来等待消息数据并且在需要的时候运行回调函数的无限循环
channel.start_consuming();
为什么要重复声明队列呢 —— 我们已经在前面的代码中声明过它了。如果我们确定了队列是已经存在的,那么我们可以不这么做,比如此前预先运行了send.py程序。可是我们并不确定哪个程序会首先运行。这种情况下,在程序中重复将队列重复声明一下是种值得推荐的做法.
或者是在cmd中运行:
python consumer.py得到同样的结果。
找到原因所在:
class ProbableAuthenticationError(AMQPConnectionError):
def __repr__(self):
return ('Client was disconnected at a connection stage indicating a '
'probable authentication error: %s' % (self.args,))
客户端在连接阶段断开连接,指示可能的认证错误
解决方法:
参考链接:http://blog.csdn.net/lvyuan1234/article/details/70145690内容如下:
我用python写了一个脚本consumer.py文件,想测试集群,consumer.py连接集群部分内容如下:
if __name__ == "__main__":
AMQP_SERVER = sys.argv[1]
AMQP_PORT = int(sys.argv[2])
#/(ctc.3) Establish broker connection settings
creds_broker = pika.PlainCredentials("guest", "guest")
conn_params = pika.ConnectionParameters( AMQP_SERVER,
port=AMQP_PORT,
virtual_host="/",
credentials=creds_broker)
ProbableAuthenticationError,意思就是登录失败
在网上查说是guest用户仅限于localhost连接,不能用于远程连接,要想用于远程连接,就必须修改rabbitmq配置文件
#vi /etc/rabbitmq/rabbitmq.config
将%% {loopback_users, [<<"guest">>]}, 改为 {loopback_users, []},改完后重启,我按照网上说的做,结果rabbitmq启动不了,还报如下错误:
{"could not start kernel pid",application_controller,"error in config file "/etc/rabbitmq/rabbitm.config\" (296): syntax error before ']' "}
我又改回来,又可以启动了,后来又在网上搜到了另一个解决办法:
Starting with RabbitMQ 3.3 you need to create a new account to use remotely, andguest/guest can only be used locally.
翻译过来就是从3.3版本开始远程连接只能新创建用户,guest只能本地连接,所以
远程访问rabbitmq:自己增加一个用户,步骤如下:
l1. 创建一个admin用户:sudo rabbitmqctl add_user admin 123123
l2. 设置该用户为administrator角色:sudo rabbitmqctl set_user_tags admin administrator
l3. 设置权限:sudo rabbitmqctl set_permissions -p '/' admin '.' '.' '.'
l4. 重启rabbitmq服务:sudo service rabbitmq-server restart
之后就能用admin用户远程连接rabbitmq server了。
创建完后,修改consumer.py文件,将连接信息改为如下
if __name__ == "__main__":
AMQP_SERVER = sys.argv[1]
AMQP_PORT = int(sys.argv[2])
#/(ctc.3) Establish broker connection settings
creds_broker = pika.PlainCredentials("admin", "123123")
conn_params = pika.ConnectionParameters( AMQP_SERVER,
port=AMQP_PORT,
virtual_host="/",
credentials=creds_broker)
就ok了,连上了集群,通过了负载均衡测试,原来就是换一个账号,别用guest,如果你的集群是在一台机器上搭建的,即单机模式的话,guest说不定可以,我没试过
三、我先是又添加了原来的guest用户;
(其他配置
1. 安装完以后erlang需要手动设置ERLANG_HOME 的系统变量。
set ERLANG_HOME=F:\Program Files\erl9.0
#环境变量`path`里加入:%ERLANG_HOME%\bin
#环境变量`path`里加入: 安装路径\RabbitMQ Server\rabbitmq_server-3.6.10\sbin
2.激活Rabbit MQ’s Management Plugin
使用Rabbit MQ 管理插件,可以更好的可视化方式查看Rabbit MQ 服务器实例的状态,你可以在命令行中使用下面的命令激活。
rabbitmq-plugins.bat enable rabbitmq_management
3.创建管理用户
rabbitmqctl.bat add_user sa 123456
4. 设置管理员
rabbitmqctl.bat set_user_tags sa administrator
5.设置权限
rabbitmqctl.bat set_permissions -p / sa ".*" ".*" ".*"
6. 其他命令
#查询用户:
rabbitmqctl.bat list_users
#查询vhosts:
rabbitmqctl.bat list_vhosts
#启动RabbitMQ服务:
net stop RabbitMQ && net start RabbitMQ (需在管理员权限下,否则出现系统错误5)
以上这些,账号、vhost、权限、作用域等基本就设置完了。)
然后,重新跟cmd 中运行程序,成功。
第二个cmd端:
四、最后--知识点补充:
send.py:
#-*-coding:utf-8 -*-
import pika
connection=pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel=connection.channel()
channel.queue_declare(queue='hello')
channel.basic_publish(exchange='',routing_key='hello',body='Hello World!')
print "[x] Send 'Hello World!'"
connection.close()
receive.py:
#!/usr/bin/env python
import pika
connection=pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel=connection.channel()
channel.queue_declare(queue='hello')
print '[*] Waiting for messages.To exit press CTRL+C'
def callback(ch,method,properties,body):
print "[*] Received %r"%(body,)
channel.basic_consume(callback,queue='hello',no_ack=True)
channel.start_consuming()
运行结果:
1、列出所有的队列
列出所有的队列:你也许希望查看 RabbitMQ 中有哪些队列、有多少消息在队列中。此时你可以使用 rabbitmqctl 工具(使用有权限的用户)
2、在运行生产者的时候,前提要确保服务器已经开启。
sudo service rabbitmq-server start #先确保服务已经开启
3、#运行receive.py 程序后,消费完队列里的消息后,并没有退出。它一直在准备获取消息,你可以通过 Ctrl-C 来中止它。