RabbitMQ

简介

RabbitMQ是一种消息中间件,用于处理来自客户端的异步消息.是一种进程间的通信或同一进程的不同线程之间的通信方式.

中间件模式的的优点:将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要 做任何修改。

消息队列常常保存在链表结构中。拥有权限的进程可以向消息队列中写入或读取 消息。

特点:

MQ是消费者-生产者模型的一个典型的代表,一端往消息队列中不断写入消息, 而另一端则可以读取或者订阅队列中的消息。MQ和JMS类似,但不同的是JMS是 JAVA消息中间件服务的一个标准和API定义,而MQ则是遵循了AMQP协议的具体实现 和产品。

  1. AMQP: 是具有现代特征的二进制协议.是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计.

  2. JMS : Java消息服务(Java Message Service)应用程序接口,是一个Java平台 中关于面向消息中间件的API,用于在两个应用程序之间,或分布式系统中发送 消息,进行异步通信。

优点:

解耦-应用耦合、异步处理、流量削锋

使用场景:不需要立即获得结果,但是并发量又需要进行控制的时候

为什么要使用RabbitMQ?

  1. 基于AMQP (高级消息队列协议)

  2. 高并发,高可用,高性能

  3. 支持插件

  4. 支持多语言

    简单队列模式

    用 Java 写两个程序;一个是生产者,他发送一个消息,另一 个是消费者,它接收消息,并且把消息打印出来。如果任务量很大,消息得不到及时的消费会造成队列积压,问题非常严重,比如内存溢 出,消息丢失等。

    简单队列-处理消息效率不高吞吐量较低不适合生产环境

    工作模式队列

    工作模式队列-消息轮询分发(Round-robin)

    特点:不管消费者数量有多少,最终消费者收到的消息都是平均的.单位时间内消息处理速度加快,提高了吞吐量.

    问题:真正的生产环境下,对于消息的处理基本不会像我们 现在看到的这样,每个消费方处理的消息数量是平均分配的,比如因为网络原因,机器cpu,内存 等硬件问题,导致部分消费者的资源被浪费.

    解决:采用消息公平分发.

    工作模式队列-消息公平分发(fair dispatch)

    消息分发采用的是默认轮询分发消息应答采用的自动应答模式,这是因为 当消息进入队列,RabbitMQ就会分派消息。它不看消费者为应答的数目,只是盲目的将第n条 消息发给第n个消费者。 为了解决这个问题,我们使用 basicQos(prefetchCount = 1) 方法,来限制RabbitMQ只 发不超过1条的消息给同一个消费者。当消息处理完毕后,有了反馈,才会进行第二次发送

    特点: 工作队列-公平分发-根据不同消费者机器硬件配置,消息处理速度不同,收到的消息 数量也不同,通常速度快的处理的消息数量比较多(能者多劳),最大化使用计算机资源。适用于生成环境。

    问题:生产者产生的消息只可以被一个消费者消费,可不可以被多个消费者消费呢?

    解决:采用发布与订阅模式。

    Publish/Subscribe-消息的发布与订阅模式队列

    当生产者把消息投送出去后,不同的消费者均可以对该消息进行消费,而不是消息被一 个消费者消费后就立即从队列中删除.

    特点:生产者发送了一条消息,用于邮件发送和短信发送的消费者均可以收到消息进行 后续处理。

    问题:生产者产生的消息所有消费者都可以消费,可不可以指定某些消费者消费呢?

    解决:采用direct路由模式。

    Routing-路由模式队列

    项目开发时会遇到这种情况: 在对项目信息输出日志进行收集时,会把日志(error warning,info)分类进行输出,这时通过 Exchange Types中的 direct 类型就可以实现,针对不同的消息,在对消息进行消费时,通过 Exchange types 以及 Routing key 设置的规则 ,便可以将不同消息路由到不同的队列中然 后交给不同消费者进行消费操作。就是指定一种规则,指定某些消费者消费.模型图如下:

  • 生产者产生的消息投给交换机

  • 交换机投送消息时的Exchange Types为direct类型

  • 消息通过定义的Routing Key被路由到指定的队列进行后续消费

  • 生产者发送了多条设置了路由规则的消息,消费者可以根据具体的

    特点:路由规则消费 对应队列中的消息,而不是所有消费者都可以消费所有消息了。

问题:生产者产生的消息如果场景需求过多需要设置很多路由规则,可不可以减少?

解决:采用topic主题模式。

Topics-主题模式队列

可以将消息路由到指 定的队列,也符合在工作中的场景去使用的一种方式,对于RabbitMq 除了 direct 模式外,Mq 同样还提供了 topics 主题模式来对消息进行匹配路由.比如在项目开发中,拿商品模块来说, 对于商品的查询功能在对商品进行查询时我们将查询消息路由到查询对应队列,而对于商品的添 加、更新、删除等操作我们统一路由到另外一个队列来进行处理,此时采用direct 模式可以实 现,但对于维护的队列可能就不太容易进行维护,如果涉及模块很多,此时对应队列数量就很 多,此时我们就可以通过 topic 主题模式来对消息路由时进行匹配,通过指定的匹配模式将消 息路由到匹配到的队列中进行后续处理。对于routing key匹配模式定义规则举例如下:

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

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

 

以上图中的配置为例:

  1. routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2,

  2. routingKey=”lazy.orange.fox”的消息会路由到Q1,Q2,

  3. routingKey=”lazy.brown.fox”的消息会路由到Q2,

  4. routingKey=”lazy.pink.rabbit”的消息会路由到Q2;

RabbitMQ消息的事务机制

在使用RabbitMQ的时候,我们可以通过消息持久化操作来解决因为服务器的异常奔溃导致的 消息丢失,除此之外我们还会遇到一个问题,当消息的发布者在将消息发送出去之后,消息到底 有没有正确到达broker代理服务器呢?如果不进行特殊配置的话,默认情况下发布操作是不会 返回任何信息给生产者的,也就是默认情况下我们的生产者是不知道消息有没有正确到达 broker的,如果在消息到达broker之前已经丢失的话,持久化操作也解决不了这个问题,因为 消息根本就没到达代理服务器,你怎么进行持久化,那么这个问题该怎么解决呢?

RabbitMQ为我们提供了两种方式:

  1. 通过AMQP事务机制实现,这也是AMQP协议层面提供的解决方案;

  2. 通过将channel设置成confirm模式来实现;

1.AMQP事物机制控制

RabbitMQ中与事务机制有关的方法有三个:

  • 过 txSelect() 开启事务

  • txCommit() 用于 提交事务,

  • txRollback() 用于回滚事务,

    事务确实能够解决producer与broker之间消息确认的问题,只有消息成功被broker接受,事 务提交才能成功,否则我们便可以在捕获异常进行事务回滚操作同时进行消息重发,但是使用事 务机制的话会降低RabbitMQ的性能,那么有没有更好的方法既能保障producer知道消息已经正 确送到,又能基本上不带来性能上的损失呢?从AMQP协议的层面看是没有更好的方法,但是 RabbitMQ提供了一个更好的方案,即将channel信道设置成confirm模式。

    2.confirm确认模式

    confirm模式最大的好处在于他是异步的,一旦发布一条消息,生产者应用程序就可以在等信 道返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用便可以通过回调 方法来处理该确认消息,如果RabbitMQ因为自身内部错误导致消息丢失,就会发送一条nack消 息,生产者应用程序同样可以在回调方法中处理该nack消息。

    注意:两种事物控制形式不能同时开启!

    Confirm确认机制代码实现

    实现生产者confirm 机制有三种方式:

    1. 普通confirm模式:每发送一条消息后,调用waitForConfirms()方法,等待服务器端 confirm。实际上是一种串行confirm了。

    2. 批量confirm模式:每发送一批消息后,调用waitForConfirmsOrDie()方法,等待服务器端 confirm。

    3. 异步confirm模式:提供一个回调方法,服务端confirm了一条或者多条消息后Client端会回 调这个方法。

    异步confirm

    异步confirm模式的编程实现最复杂

    优点:执行效率高,不需要等待消息执行完,只需要监听消息即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值