RabbitMQ是一个程序与程序之间通信的方法,或者可以理解为一种专用的通道,专门用来负责消息的读取和写入。应用程序通过在RabbitMQ中读写消息来通信,程序与程序之间无需专门的链接,而是直接通过RabbitMQ来进行数据的读写。RabbitMQ将会采用异步的方式来分发消息,是一种经典的生产者与消费者的模式,多个消费者由RabbitMQ来负责协调,并且保证每一条消息都能得到可靠的执行。假如一条消息在执行过程中出现了错误,RabbitMQ并不会放弃这条消息,而是专由其他的消费者来处理这条消息。
RabbitMQ和Celery到底有什么区别?上面我们已经提到过,RabbitMQ是负责消息的生产和消费,我们可以理解为,RabbitMQ是一个仓库的中转站,所有的程序消息都发送给RabbitMQ,然后由RabbitMQ来负责把这些消息来运输给消费者。但是RabbitMQ的侧重点在于,消息的读写。比如说我们有一个仓库A,我想把仓库A里面的全部货物,经过不同的路线,最终运输到仓库B里面。如果我们使用RabbitMQ,是可以完成这种操作,但是这其中包含了大量复杂的逻辑,我们需要自己去写。于是有人就提供了一种现成的方案,那就是Celery。
Celery主要负责的就是异步的任务队列,它本身不提供任何数据的存取,只关注如何把数据,异步,安全,高效,可靠的运输到另一个地点,并且在对方处理完成以后,再把响应数据通知给对应的方法。
我们拿爬虫来讲,假如我要爬一个网站A,如果按照正常的逻辑。发送一个请求到网站A,然后网站A收到了我的请求,把响应的页面传给我,我再负责解析。这其中就包含了一个问题,比如说A网站的服务器很卡,在我发送数据以后,到他处理完成,这段过程用了三四秒的时间。那么这段时间我的程序一直是处于一种等待状态,等待响应的完成,这样就造成了大量的资源浪费。
使用Celery的好处就是,在我们请求发送出去以后,Celery就立刻开始去发送下一个任务,它会把所有的任务都快速的发送出去,并不等待任务响应完成。当某一个任务响应回来时,Celery再去通知具体的人来处理响应的数据,然后继续分发任务。
所以RabbitMQ和Celery最大区别就是,RabbitMQ提供了一种可靠的消息存取的服务,而Celery负责高效的分发这些消息。
在Ubuntu安装RabbitMQ这里我使用的是vultr的云主机,在之前的文章中有介绍如何注册创建vultr云主机,不会的请戳链接,这里将不再介绍任何关于创建和连接的问题,当然也可以使用自己本地的虚拟机或者是其他的云服务器,如阿里云,谷歌云。
这里我们使用的是Ubuntu 14.04 x64版本的
首先为了避免各种签名错误,我们把公钥加入可信任的列表:
wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
sudo apt-key add rabbitmq-signing-key-public.asc
当我们看到控制台显示:
OK
说明我们导入公钥成功。
然后我们开始更新和安装RabbitMQ:
sudo apt-get update
sudo apt-get install rabbitmq-server
当控制台询问我们是否安装的时候,输入y
然后回车。
当看到结尾出现如下信息说明安装成功:
Adding group
rabbitmq' (GID 110) ... Done. Adding system user
rabbitmq’ (UID 105) …
Adding new userrabbitmq' (UID 105) with group
rabbitmq’ …
Not creating home directory `/var/lib/rabbitmq’.
- Starting message broker rabbitmq-server [ OK ]
Processing triggers for libc-bin (2.19-0ubuntu6.11) …
Processing triggers for ureadahead (0.100.0-16) …
RabbitMQ安装成功以后,会建立一个默认的guest账户,用户名和密码都是guest。我们在shell里面输入rabbitmqctl status
可以查看RabbitMQ的运行情况。
看到如下输出,说明我们RabbitMQ已经成功运行:
输入rabbitmqctl stop
将关闭RabbitMQ服务器,看到如下信息说明关闭成功:
Stopping and halting node rabbit@chenshen …
…done.
此时再次输入rabbitmqctl status
,将会看到如下错误信息提示我们没有运行RabbitMQ:
那么我们如何启动RabbitMQ呢,有些同学可能会想,肯定是输入rabbitmqctl start
。不过很可惜,RabbitMQ并不是依靠这种方式来启动的,而是使用另一个命令:rabbitmq-server -detached
,参数-detached
是使用守护进程在后台运行,如果不加此参数,则关闭命令行后RabbitMQ会自动退出。
运行以后我们会得到一个警告:
Warning: PID file not written; -detached was passed.
需要注意的是,这个警告是正常的警告,并非是异常信息,如果不放心可以查看RabbitMQ的运行日志和错误日志:
cat /var/log/rabbitmq/startup_log
cat /var/log/rabbitmq/startup_err
看到这种如下信息,说明我们启动正常:
需要注意的是,上面的警告信息是正常的,并非是我说的,而是官方文档说的:
Options
-detached
Start the server process in the background. Note that this will cause the pid not to be written to the pid file.For example:
rabbitmq-server -detached
Runs RabbitMQ AMQP server in the background.
大概的意思就是,如果我们加了-detached
参数在后台运行的话,这会让pid不能被写入pid文件。
程序员惯例,什么都先来一个Hello World。
安装pika
我们只是安装了RabbitMQ,但是我们如果想要在Python中使用,就需要安装具体的库:
RabbitMQ使用的是AMQP协议。要使用它,你就必须需要一个使用同样协议的库。
官方文档中,使用的pika,所以我们也使用pika。
警告:需要注意的是,此时我们是在另一台电脑安装,并非在服务器安装!
我使用的是Windows10操作系统,Python版本为3.5,请大家保持同步。
使用下面的命令安装:
pip install pika -i https://pypi.douban.com/simple/
看到如下信息说明安装成功:
Successfully installed pika-0.10.0
注意:我这里默认安装最新的,是0.10.0版本,随着时间的推移,可能会有较大的变化,如果大家哪天发现按照本文无法正常操作,有可能是版本升级的问题。此时,大家可以这么做:
pip uninstall pika
pip install pika==0.10.0 -i https://pypi.douban.com/simple/
卸载后,指定安装版本。
终于要开始了
我们在远程连接RabbitMQ之前,需要新建一个用于远程连接的用户,默认的guest用户只接受127.0.0.1的本地连接。
警告:此时我们的操作又是在服务器了!
* 查看用户列表
sudo rabbitmqctl list_users
可以看到,我们只有一个默认的guest用户,它的权限是administrator。
警告兼友情提示:下面的命令不要直接复制,因为中文编码和shell的编码不一样,你直接在上面改会造成,看似没有字符,实际上还有一些中文字符编码在里面,导致你到时候用户名不是你建的用户名,而是有一些你看不到的编码在里面。当然,这种可能性非常小,但是直接复制报错的几率是很大的,因为你没把字符编码删干净,聪明的人都知道在本地的文本文档改好,然后再复制运行。
* 创建用户,如果你连用户名和密码改成自己想设置的都不知道,我不建议你学编程了
sudo rabbitmqctl add_user 用户名 密码
* 查看一下有没有创建成功,可以看到新建了一个用户cheshen[],他的权限为空
sudo rabbitmqctl list_users
* 赋予超级管理员权限,这个用户名一看就是你上面建的好伐
sudo rabbitmqctl set_user_tags 用户名 administrator
* 再次查看
sudo rabbitmqctl list_users
* 最重要的一步,设置监听请求的地址
rabbitmqctl set_permissions -p "/" 用户名 ".*" ".*" ".*"
Listing users …
cheshen [administrator]
guest [administrator]
…done.
终于可以写代码了!!!
开始写代码
本地Windows环境了
新建文件send.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2017-04-02 01:20:41
# @Author : 车神 (meteorshield@gmail.com)
# @Link : http://www.cheshen.wiki
# @Version : $Id$
import pika
# 就是我们刚才创建的那个
credentials = pika.PlainCredentials('用户名', '密码')
parameters = pika.ConnectionParameters(credentials=credentials)
parameters = pika.ConnectionParameters('服务器IP',5672,'/',credentials)
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
channel.queue_declare(queue='hello')
print(' [*] Waiting for messages. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] Received %r" % (body,))
channel.basic_consume(callback,
queue='hello',
no_ack=True)
channel.start_consuming()
新建receive.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2017-04-02 01:20:41
# @Author : 车神 (meteorshield@gmail.com)
# @Link : http://www.cheshen.wiki
# @Version : $Id$
import pika
credentials = pika.PlainCredentials('用户名', '密码')
parameters = pika.ConnectionParameters(credentials=credentials)
parameters = pika.ConnectionParameters('服务器IP',5672,'/',credentials)
connection = pika.BlockingConnection(parameters)
channel = connection.channel()
channel.queue_declare(queue='hello')
print(' [*] Waiting for messages. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] Received %r" % (body,))
channel.basic_consume(callback,
queue='hello',
no_ack=True)
channel.start_consuming()
在本地的控制台输入:
python send.py
然后会看到:
[x] Sent ‘Hello World.’
启动另一个命令行再输入:
python receive.py
然后会看到:
[*] Waiting for messages. To exit press CTRL+C
[x] Received b’Hello World.’
这个进程并不会退出,而是等待我们发送新的信息,再次运行python send.py
可以看到receive的窗口再次输出信息。
运行可能会报错:pika.exceptions.ConnectionClosed
这是因为我们的服务器在美国,连接超时了,多次连接,或者开启系统代理就可以了。
多来几次就可以了
下章我们详细解释这些方法都是干啥的。
后记感谢大家的支持,本文原创作者:秋名山车神
转载请注明出处,大家有任何的问题,都可以通过我博客上的联系方式与我取得联系。
END
共同学习,写下你的评论
评论加载中...
作者其他优质文章