背景:
RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现。AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有很多公开标准(如 COBAR的 IIOP ,或者是 SOAP 等),但是在异步消息处理中却不是这样,只有大企业有一些商业实现(如微软的 MSMQ ,IBM 的 Websphere MQ 等),因此,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等联合制定了 AMQP 的公开标准。
RabbitMQ是由RabbitMQ Technologies Ltd开发并且提供商业支持的。该公司在2010年4月被SpringSource(VMWare的一个部门)收购。在2013年5月被并入Pivotal。其实VMWare,Pivotal和EMC本质上是一家的。不同的是VMWare是独立上市子公司,而Pivotal是整合了EMC的某些资源,现在并没有上市。
工作原理:
组成部分说明如下:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。消息发布接收流程:-----发送消息-----1、生产者和Broker建立TCP连接。2、生产者和Broker建立通道。3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。4、Exchange将消息转发到指定的Queue(队列)----接收消息-----
1、消费者和Broker建立TCP连接2、消费者和Broker建立通道3、消费者监听指定的Queue(队列)4、当有消息到达Queue时Broker默认将消息推送给消费者。5、消费者接收到消息。交换机的类型:
fanout:fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。
direct:direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中
topic:前面提到的direct规则是严格意义上的匹配,换言之Routing Key必须与Binding Key相匹配的时候才将消息传送给Queue,那么topic这个规则就是模糊匹配,可以通过通配符满足一部分规则就可以传送。它的约定是:
routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
binding key与routing key一样也是句点号“. ”分隔的字符串
binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)
header:headers类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。该类型的Exchange没有用到过(不过也应该很有用武之地),所以不做介绍。
rabbitmq的工作模式:
工作队列模式:
work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息。应用场景:对于 任务过重或任务较多情况使用工作队列可以提高任务处理的速度。测试:1、使用入门程序,启动多个消费者。2、生产者发送多个消息。结果:1、一条消息只会被一个消费者接收;2、rabbit采用轮询的方式将消息是平均发送给消费者的;3、消费者在处理完某条消息后,才会收到下一条消息。
发布订阅模式:1、每个消费者监听自己的队列。2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息
使用场景:当用户注册之后要发送邮箱和验证码
roulingkey 路由模式:1、每个消费者监听自己的队列,并且设置routingkey。2、生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。
topic 路由模式:1、每个消费者监听自己的队列,并且设置带统配符的routingkey。2、生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列。
header模式
header模式与routing不同的地方在于,header模式取消routingkey,使用header中的 key/value(键值对)匹配队列。案例:根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种通知类型都接收的则两种通知都有效。
ConnectionFactory、Connection、Channel
ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。 Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。
Connection就是建立一个TCP连接,生产者和消费者的都是通过TCP的连接到RabbitMQ Server中的,这个后续会再程序中体现出来。
Channel虚拟连接,建立在上面TCP连接的基础上,数据流动都是通过Channel来进行的。为什么不是直接建立在TCP的基础上进行数据流动呢?如果建立在TCP的基础上进行数据流动,建立和关闭TCP连接有代价。频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。
至于这个这些操作可以看看之前的代码
分析:
1 在实际开发中,应该通常使用topic模式。也就是通配符模式,可以根据通配符模式来进行匹配,这样自定义规则就可以了,
2 当一个生产者多个消费者时候,消费者会是采用轮询的方式进行消费不会重复消费
3 rabbitmq的各种模式对应相对应的交换机,topic模式是一种通配符模式这个模式跟activemq中的topic消息时存在区别,在activemq中,topic是一种类似udp消息模式,可以多个消费者同时消费一个消息,但是不能确定百分百都消费,
会存在有些消费米有被消费,在rabbitmq中不存在这种模式
4 消息重发;当消费者接受到消息之后,会进行消费,那么如果这个时候出现异常了,自动签收就会存在消息消费了,那么订单消息就会丢失,所以应该采用手动回签在代码里面避免这个情况存在
5 百分百可靠性投递消息:设置手动回签,或者采用延时队列发送消息。
6 可以使用rabbitmq进行分布式事物处理,采用最终一致性来避免分布式事物