标签:
rabbitmq作为成熟的企业消息中间件,实现了应用程序间接口调用的解耦,提高系统的吞吐量。
1.RabbitMQ组成
对于一个数据从Producer到Consumer的正确传递,还有三个概念需要明确:exchanges, queues and bindings。
还有几个概念是上述图中没有标明的,那就是Connection(连接),Channel(通道,频道)。
那么,为什么使用Channel,而不是直接使用TCP连接?
对于OS来说,建立和关闭TCP连接是有代价的,频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。对于Producer或者Consumer来说,可以并发的使用多个Channel进行Publish或者Receive。有实验表明,1s的数据可以Publish10K的数据包。当然对于不同的硬件环境,不同的数据包大小这个数据肯定不一样,但是我只想说明,对于普通的Consumer或者Producer来说,这已经足够了。如果不够用,你考虑的应该是如何细化split你的设计。
Exchange是属于Vhost的。同一个Vhost不能有重复的Exchange名称。 Exhange有四种类型:fanout,Direct,header,topic。
Exchange接受Producer发送的Message并根据不同路由算法将Message发送到Message Queue。
从架构图可以看出,Procuder Publish的Message进入了Exchange。接着通过“routing keys”, RabbitMQ会找到应该把这个Message放到哪个queue里。queue也是通过这个routing keys来做的绑定。
Exchange的绑定功能,可以绑定queue,也可以绑定Exchange。这个看具体业务了。如果绑定数据,需要在分发或者重新被分派,使用To Exchange绑定。如果要被直接处理,使用queue绑定。如果Exchange绑定了Queue,如果Route Key不对,也会导致数据不可达,被丢掉。(一个数据可以被Queue处理,需要Exchange绑定Queue,并且在Message发送的时候,Route Key 与绑定的Key相等。我们发送一个空数据,Route Key随便制定了Hello,消息虽然发送,但是客户获得失败。
有四种类型的Exchanges:direct, fanout,topic。 每个实现了不同的路由算法(routing algorithm)。
Queue:
Message Queue会在Message不能被正常消费时将其缓存起来,但是当Consumer与Message Queue之间的连接通畅时,Message Queue将Message转发给Consumer。
Message由Header和Body组成,Header是由Producer添加的各种属性的集合,包括Message是否客被缓存、由哪个Message Queue接受、优先级是多少等。而Body是真正需要传输的APP数据。
Exchange与Message Queue之间的关联通过Binding来实现。Exchange在与多个Message
Queue发生Binding后会生成一张路由表,路由表中存储着Message Queue所需消息的限制条件即Binding
Key。当Exchange收到Message时会解析其Header得到Routing Key,Exchange根据Routing
Key与Exchange Type将Message路由到Message Queue。
Binding Key由Consumer在Binding Exchange与Message Queue时指定,而Routing Key由Producer发送Message时指定,两者的匹配方式由Exchange Type决定。
Exchange Type分为Direct(单播)、Topic(组播)、Fanout(广播)。当为Direct(单播)时,Routing
Key必须与Binding Key相等时才能匹配成功,当为Topic(组播)时,Routing Key与Binding
Key符合一种模式关系即算匹配成功,当为Fanout(广播)时,不受限制。默认Exchange Type是Direct(单播)。
routing:exchange和queue之间绑定的媒介,成为routing key。
message acknowledgment: 消息确认,解决消息确认问题,只有收到ack之后才能从消息系统中删除。
message durability: 消息持久化,当rabbitmq退出或崩溃后,会把queue中的消息持久化。但注意,RabbitMQ并不能百分之百保证消息一定不会丢失,因为为了提 升性能,RabbitMQ会把消息暂存在内存缓存中,直到达到阀值才会批量持久化到磁盘,也就是说如果在持久化到磁盘之前RabbitMQ崩溃了,那么就 会丢失一小部分数据,这对于大多数场景来说并不是不可接受的,如果确实需要保证任务绝对不丢失,那么应该使用事务机制。
每个virtual host本质上都是一个RabbitMQ Server,拥有它自己的queue,exchange,和bind rule等等。这保证了你可以在多个不同的application中使用RabbitMQ。
RabbitMQ的Vhost主要是用来划分不同业务模块。不同业务模块之间没有信息交互。Vhost之间相互完全隔离,不同Vhost之间无法共享Exchange和Queue。因此Vhost之间数据无法共享和分享。如果要实现这种功能,需要Vhost之间手动构建对应代码逻辑。
Vhost其实在用户之间是透明的,Vhost可以被多个用户访问,而一个用户可以同时访问多个Vhost。 例如:peter可以同时访问"/"和"/vhost"。
Virtual Host是个虚拟概念,可以持有一些Exchange和Message Queue。一个Virtual Host可以是一台服务器,也可以是由多台服务器组成的集群。Exchange和Message Queue可以分别部署在一台或者多台服务器上。
2 应用场景
言归正传。RabbitMQ,或者说AMQP解决了什么问题,或者说它的应用场景是什么?
对于一个大型的软件系统来说,它会有很多的组件或者说模块或者说子系统或者(subsystem or Component or submodule)。那么这些模块的如何通信?这和传统的IPC有很大的区别。传统的IPC很多都是在单一系统上的,模块耦合性很大,不适合扩展(Scalability);如果使用socket那么不同的模块的确可以部署到不同的机器上,但是还是有很多问题需要解决。比如:
1)信息的发送者和接收者如何维持这个连接,如果一方的连接中断,这期间的数据如何方式丢失?
2)如何降低发送者和接收者的耦合度?
3)如何让Priority高的接收者先接到数据?
4)如何做到load balance?有效均衡接收者的负载?
5)如何有效的将数据发送到相关的接收者?也就是说将接收者subscribe 不同的数据,如何做有效的filter。
6)如何做到可扩展,甚至将这个通信模块发到cluster上?
7)如何保证接收者接收到了完整,正确的数据?
AMDQ协议解决了以上的问题,而RabbitMQ实现了AMQP。
标签:
原文地址:http://www.cnblogs.com/200911/p/4856835.html