RabbitMQ理解

引言

       你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用、通讯的问题而苦恼、挣扎?如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题。
       消息服务擅长于解决多系统、异构系统间的数据交换(消息通知/通讯)问题,你也可以把它用于系统间服务的相互调用(RPC)。本文将要介绍的RabbitMQ就是当前最主流的消息中间件之一。


消息的大体发送流程是:

生产者发送消息到指定的exchange,然后根据exchange和routingKey,再将信息发送到一个或者多个queue中,最后queue将消息发送至消费者。

几个概念说明:
Broker:
它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输,
Exchange
:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:
消息的载体,每个消息都会被投到一个或多个队列。
Binding:
绑定,它的作用就是把exchangequeue按照路由规则绑定起来.
Routing Key:
路由关键字,exchange根据这个关键字进行消息投递。
vhost:
虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。
Producer:
消息生产者,就是投递消息的程序.
Consumer:
消息消费者,就是接受消息的程序.
Channel:
消息通道,在客户端的每个连接里,可建立多个channel.

1、exchange

RabbitMQ中,生产者需要将消息先发送至Exchange,然后由exchange转发至queue,这需要实现exchange与queue进行绑定。


1.1  routing key

       生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联合使用才能最终生效。在Exchange Type与binding key固定的情况下(在正常使用时一般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过指定routing key来决定消息流向哪里。RabbitMQ为routing key设定的长度限制为255 bytes。

1.2  bindingKey

       在绑定(Binding)Exchange与Queue的同时,一般会指定一个binding key;消费者将消息发送给Exchange时,一般会指定一个routing key;当binding key与routing key相匹配时,消息将会被路由到对应的Queue中。这个将在Exchange Types章节会列举实际的例子加以说明。在绑定多个Queue到同一个Exchange的时候,这些Binding允许使用相同的binding key。binding key 并不是在所有情况下都生效,它依赖于Exchange Type,比如fanout类型的Exchange就会无视binding key,而是将消息路由到所有绑定到该Exchange的Queue。

1.3exchange 类型

        RabbitMQ常用的Exchange Type有fanout、direct、topic、headers这四种。

        Direct:direct类型的Exchange会把消息路由到那些binding keyrouting key完全匹配的Queue

        Fanout:fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。

        Topic:前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:

       routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”

       binding key与routing key一样也是句点号“. ”分隔的字符串

       binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)

headers:略。

2、queue

       Queue(队列)是rabbitMQ中的内部对象,用于存储消息。rabbitMQ中的消息只能存储在queue中,生产者生产的消息最终都会投递到queue中,消费者可以从queue中获取消息进行消费。多个消费者可以订阅同一个Queue进行消费,此时queue的消息是被均分到各个消费者上,而不是每个消费者都收到所有的消息。

2.1 消息应答

       在实际应用中,可能会发生消费者收到Queue中的消息,但没有处理完成就宕机(或出现其他意外)的情况,这种情况下就可能会导致消息丢失。为了避免这种情况发生,我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ,RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理。这里不存在timeout概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开。
这里会产生另外一个问题,如果我们的开发人员在处理完业务逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug——Queue中堆积的消息会越来越多;消费者重启后会重复消费这些消息并重复执行业务逻辑,另外pub message是没有ack的。

2.2 消息持久化

       如果我们希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,我们可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。但依然解决不了小概率丢失事件的发生(比如RabbitMQ服务器已经接收到生产者的消息,但还没来得及持久化该消息时RabbitMQ服务器就断电了),如果我们需要对这种小概率事件也要管理起来,那么我们要用到事务。由于这里仅为RabbitMQ的简单介绍,所以这里将不讲解RabbitMQ相关的事务。

引用资料:

http://www.2cto.com/kf/201702/597200.html

http://blog.csdn.net/dandanzmc/article/details/52244529

http://blog.csdn.net/u011991249/article/details/53200856

http://blog.csdn.net/olaking/article/details/47009753

http://blog.csdn.net/whycold/article/details/41119807

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值