为什么要用rabbitmq中的问题

    MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序或者模块对模块的通信方法MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息而另一端则可以读取队列中的消息。

(1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端 这有一个问題是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西.

(2)并行方式:将注册信息写入数据库后,发送邮件的同時,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。

    假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms虽然并发已经提高了处理时间,但是,前面说过,邮件和短信对我们正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注冊成功,因而是写入数据库后就返回.

    引入消息队列后把发送邮件,短信不是必须的业务逻辑异步处理

    由此可以看出,引入消息队列后,用户的響应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍

    场景:双11是購物狂节,用户下单后,订单系统需要通知库存系统,传统的做法就是订单系统调用库存系统的接口.

  这种做法有一个缺点:

  • 当库存系统出现故障时,訂单就会失败。(这样马云将少赚好多好多钱^ ^)
  • 订单系统和库存系统高耦合.
  • 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
  • 库存系统:订阅下单的消息,获取下单消息,进行库操作。
  • 就算库存系统出现故障,消息队列也能保证消息的可靠投递,不會导致消息丢失(马云这下高兴了).

  流量削峰一般在秒杀活动中应用广泛

  场景:秒杀活动一般会因为流量过大,导致应用挂掉,为了解决这个问題一般在应用前端加入消息队列。

1.可以控制活动人数超过此一定阀值的订单直接丢弃(我为什么秒杀一次都没有成功过呢^^)

2.可以缓解短时間的高流量压垮应用(应用程序按自己的最大处理能力获取订单)

1.用户的请求,服务器收到之后,首先写入消息队列,加入消息队列长度超过最大值,則直接抛弃用户请求或跳转到错误页面.

2.秒杀业务根据消息队列中的请求信息,再做后续处理.

  队列是为什么要用rabbitmq的内部对象用于存储消息。生产者(下图中的P)生产消息并投递到队列中消费者(下图中的C)可以从队列中获取消息并消费。

  多个消费者可以订阅同一个队列這时队列中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理

    刚才在3.1中,我们看到生产者将消息投递到队列中实际上这在为什么要用rabbitmq中这种事情永远都不会发生。实际的情况是生产者将消息发送到Exchange(交换器,下图中的X)再通过Binding將Exchange与Queue关联起来。

生产者在将消息发送给Exchange的时候一般会指定一个routing key,来指定这个消息的路由规则生产者就可以在发送消息给Exchange时,通过指定routing key來决定消息流向哪里

  •   fanout:把所有发送到该Exchange的消息投递到所有与它绑定的队列中。

附上一张为什么要用rabbitmq的结构图:

1、可以自动创建队列也可鉯手动创建队列,如果自动创建队列那么是谁负责创建队列呢?是生产者还是消费者?

    如果队列不存在当然消费者不会收到任何的消息。但是如果队列不存在那么生产者发送的消息就会丢失。所以为了数据不丢失,消费者和生产者都可以创建队列那么如果创建┅个已经存在的队列呢?那么不会有任何的影响需要注意的是没有任何的影响,也就是说第二次创建如果参数和第一次不一样那么该操作虽然成功,但是队列属性并不会改变

队列对于负载均衡的处理是完美的。对于多个消费者来说为什么要用rabbitmq使用轮询的方式均衡的發送给不同的消费者。

    默认情况下如果消息已经被某个消费者正确的接收到了,那么该消息就会被从队列中移除当然也可以让同一个消息发送到很多的消费者。

如果一个队列没有消费者那么,如果这个队列有数据到达那么这个数据会被缓存,不会被丢弃当有消费鍺时,这个数据会被立即发送到这个消费者这个数据被消费者正确收到时,这个数据就被从队列中删除

    那么什么是正确收到呢?通过ack每个消息都要被acknowledged(确认,ack)我们可以显示的在程序中去ack,也可以自动的ack如果有数据没有被ack,那么:

为什么要用rabbitmq Server会把这个信息发送到丅一个消费者

如果这个app有bug,忘记了ack那么为什么要用rabbitmqServer不会再发送数据给它,因为Server认为这个消费者处理能力有限

而且ack的机制可以起到限鋶的作用(Benefitto throttling):在消费者处理完成数据后发送ack,甚至在额外的延时后发送ack将有效的均衡消费者的负载。

}

在面试大型互联网公司的时候佷可能会被问题:

  1.在何种场景下使用了消息中间件?

  2.为什么要在系统里引入消息中间件

链式调用是我们在写程序时候的一般流程,为了唍成一个整体功能会将其拆分成多个函数(或子模块),比如模块A调用模块B模块B调用模块C,模块C调用模块D但在大型分布式应用中,系统间的RPC交互繁杂一个功能背后要调用上百个接口并非不可能,这种架构有如下几个劣势

这些接口之间耦合比较严重每新增一个下遊功能,都要对上有的相关接口进行改造;举个例子:假如系统A要发送数据给系统B和C发送给每个系统的数据可能有差异,因此系统A对要發送给每个系统的数据进行了组装然后逐一发送;当代码上线后,新增了一个需求:把数据也发送给D此时就需要修改A系统,让他感知箌D的存在同时把数据处理好给D。在这个过程中你会看到每接入一个下游系统,都要对A系统进行代码改造开发联调的效率很低。其如丅图:

2、 面对大流量并发时容易被冲垮每个接口模块的吞吐能力是有限的这个上限能力如果堤坝,当大流量(洪水)来临时容易被冲垮。

3、 存在性能问题上是同步调用,整体的服务性能遵循“木桶理论”即链路中最慢的那个接口。比如A调用B/C/D都是50ms但此时B又调用叻B1,花费2000ms那么直接就拖累了整个服务性能。

根据上述的几个问题在设计系统时可以明确要达到的目标:

1、 要做到系统解耦当新的模塊接进来时可以做到代码改动最小;

2、 设置流量缓冲池可以让后端系统按照自身吞吐能力进行消费不被冲垮;

3、 强弱依赖梳理,将非关键调用链路的操作异步化提升整体系统的吞吐能力比如上图中A、B、C、D是让用户发起付款然后返回付款成功提示的几个关键流程,而B1是通知付款后通知商家发货的模块那么实质上用户对B1完成的时间容忍度比较大(比如几秒之后),可以将其异步化

在现在的系统視线中,MQ使用的可以完美的解决这些问题的利器。下图是使用了MQ的简单架构图可以看到MQ在最前端对流量进行蓄洪,下游的系统ABC只与MQ打茭道通过事先定义好的消息格式来解析。

引入MQ之后的、交互方式与最初的链式调用架构非常不同虽然可以解决上文提到的问题,但也偠充分理解其原理特性来避免其带来的副作用这里以消息队列如何保证“消息的可靠投递”为切入点,来看看MQ的实现方式

2.MQ将消息持久囮后,发送Ack消息给Client此处有可能因为网络问题导致Ack消息无法发送到Client,那么Client在等待超时后会重传消息

3.Client收到Ack消息后,认为消息已经投递成功

2.Client得到消息并做完业务逻辑

3.Client发送Ack消息给MQ,通知MQ删除该消息此处有可能因为网络问题导致Ack失败,那么Client会重复消息这里就引出消费幂等嘚问题

4.MQ将已消费的消息删除

看完了这篇分享,不知道你对自己的Java学习是不是有了更多的感悟~ 







文章来源网络版权归作者本人所有,如侵犯到原作者权益请与我们联系删除

}

我要回帖

更多关于 为什么要用rabbitmq 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信