RabbitMq介绍

来源:互联网 发布:带网络的电视机 编辑:程序博客网 时间:2024/06/10 12:33
项目的适用场景:系统中使用到了第三方的监测系统,每次使用都要以http的请求去获取一些信息,用户在我们系统中发出请求后,我们将要再去请求第三方的接口。显而易见这样的应用场景会出现一些问题,例如:
1.假设第三方的接口处理的时间很长,那么直接的请求返回,会让用户处在一种等待的状态下,这怎么解决?
2.如果第三方的接口的服务器当掉了,那么系统这时候应该如何处理?
第一个问题的答案是“异步”,第二个问题的答案是“重试机制”。


一种简单的处理方法:当用户请求系统的时候,可以将当前的请求放在一个空间下面比如文件,内存(redis, mongodb等),数据库,然后返回给用户,而在后端用另一个程序去读取并处理空间下面的请求。
这样的处理方法适合单任务操作,为什么?如果有多个外部程序一起处理空间的请求的话,问题会变的复杂起来。这时候会要考虑到处理实体(请求)的状态以及一系列的并发问题。而这样的解决方法会让人感觉到很“业余”。


而RabbitMq就让这些问题迎刃而解了:
    首先.message queue的概念会让人感觉到就是为这样的场景而诞生的(反正我是这么想的)。
    第二.rabbitmq已经帮你处理了多个处理者并行处理的情形,而你只需要写很少的代码(好像只有一行)。即使在一个处理者正在处理的时候当掉的话,当前的处理实体也会被server交付给其他的处理者处理,除非你不想那么干。


名词解释:
处理实体: 队列中储存的处理单元,用于被处理者处理,每次处理一个。


1.RabbitMq结构
RabbitMq分为三部分.
(1).mq的服务器(队列): 服务器的作用是接受生产者发送过来的处理实体,并保存。
(2).生产者:产生处理实体,向队列中添加, mq的客户端。
(3).处理者:接受mq服务器分发的处理实体并处理。


2. 运行测试RabbitMq
2.1. 下载并安装:
     wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.2/rabbitmq-server_2.8.2-1_all.deb
2.2. 启动server:
     rabbitmq-server -detached     
2.3. 安装客户端(python pika):
     pip install pika
2.4. 生产者代码:
import pikainfor = "aaaaaaaa"connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.queue_declare(queue='hel')channel.basic_publish(exchange='', routing_key='hel', body=infor)

2.5. 运行后在服务器的机器上测试

rabbitmqctl list_queues

Listing queues ...
hel1
...done.
成功
2.6. 处理者代码:
import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.queue_declare(queue='hel')def callback(ch, method, properties, body):    print bodychannel.basic_consume(callback,queue='hel',no_ack=True)channel.start_consuming()

3.多处理者的情形
由多个处理者并行处理处理实体,注意的问题就是:当一个处理实体在处理中的时候,处理该实体的处理者当掉的话,那么该实体怎么做处理。rabbitmq给了我们选择。
为了保证消息不会被丢失,rabbitmq支持消息确认,一个消息确认就是指当处理者发送一个消息告诉mq服务器:特定的消息已经接受到了并且被处理了,然后mq服务器就可以删除此消息了。消息的处理时长是任意的,mq服务器不会因为这个消息处理的时间太长了,就将这个消息转给了其他处理者处理。必须等到某个处理者链接不上了之后才会转发正在处理的消息。
处理者代码:
import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))channel = connection.channel()channel.queue_declare(queue='hel')def callback(ch, method, properties, body):    print body    ch.basic_ack(delivery_tag = method.delivery_tag)channel.basic_consume(callback,queue='hel')channel.start_consuming()
"ch.basic_ack(delivery_tag = method.delivery_tag)"这样就保证了消息确认了。


4.搭建rabbitmq服务器集群
服务器集群的概念和优点就不罗嗦了,
4.1 启动第一台机器上的服务器:
root@swallowsea:~# rabbitmq-server -detached
运行:
root@swallowsea:~# rabbitmqctl cluster_status
查看服务器节点状态:
Cluster status of node rabbit@swallowsea ...
[{nodes,[{disc,[rabbit@swallowsea]}]},{running_nodes,[rabbit@swallowsea]}]
...done.
当前运行的节点:rabbit@swallowsea,disc中只有一个服务器节点在运行
4.2 运行第二台机器上的服务器
4.2.1 root@test:~# rabbitmq-server -detached
4.2.2 停止app
root@test:~# rabbitmqctl stop_app 
4.2.3 重置app
root@test:~# rabbitmqctl reset
4.2.4
*1 erlang使用cookie来允许各个节点之间的通信,所以两个节点之间的cookie必须相同。
从第一台服务器/var/lib/rabbitmq/.erlang.cookie文件中拷贝出cookie,将它粘贴到第二台服务器上的.erlang.cookie
(它们所在的位置肯呢个不一样,你可以使用locate来查找该文件)
?*2 为了使第二台机器上必须能访问到第一台服务器,将第二台机器上的hosts文件添加记录:
    192.168.18.84   swallowsea
    第一台的机器节点名称为: rabbit@swallowsea
4.2.5将节点添加到第一台服务器中
root@test:~# rabbitmqctl cluster rabbit@swallowseaClustering node rabbit@test with [rabbit@swallowsea] ......done.

成功 OK
启动:
root@test:~# rabbitmqctl start_app
查看状态:
  
  root@test:~# rabbitmqctl cluster_status    Cluster status of node rabbit@test ...    [{nodes,[{disc,[rabbit@swallowsea]},{ram,[rabbit@test]}]},     {running_nodes,[rabbit@swallowsea,rabbit@test]}]    ...done.

可以发现两个节点都已经运行了。
用rabbitmqctl list_queues测试发现两个节点的数据都是一样的了。

5 节点之间的关系
节点分为两种类型的节点,第一种称作RAM,第二种称作DISK, 顾名思义RAM节点仅仅将状态信息存放在内存中,而DISK节点可以将信息保存在内存中和磁盘中。因为RAM节点不许要写磁盘,所以它的性能能更好一点。
其实用 rabbitmqctl cluster rabbit@swallowsea 命令的时候cluster后面指定的节点名称就是该集群中DISK的节点名称
所以可以利用cluster命令来进行DISK与RAM节点类型的更换。
原创粉丝点击