RabbitMQ那些事

672 阅读4分钟

这是我参与更文挑战的第3天,活动详情查看: 更文挑战

我们为什么要用消息队列?

消息队列即Message Queue。

说到为什么要使用MQ,我们就不得不说MQ的使用场景。其主要使用场景有:

  1. 解耦
  2. 削峰
  3. 异步
  4. 流量监控
  5. 分布式事务的可靠消费和可靠生产
  6. 索引、缓存、静态化处理数据同步
  7. 日志监控(ELK)
  8. 下单、订单分发、抢票

其最主要的作用便是将串行的操作并行化。为实现这一目的,我们当然可以自己写并行程序实现,但用异步线程池有几个缺点:

  1. 耦合度高
  2. 需要自己维护线程池
  3. 消息可能会丢失,要自己做消息补偿
  4. 要自己写保证消息的可靠性
  5. 如果服务器承载不了,要自己写高可用

这便为消息队列的产生提供了条件。

建议,如果你仅仅还只是一个初创公司建议还是使用单体架构,最多加个缓存中间件即可,不要盲目追求新或者所谓的高性能,而追求的背后一定是业务的驱动和项目的驱动,因为一旦追求就意味着你的学习成本,公司的人员结构以及服务器成本,维护和运维的成本都会增加,所以需要谨慎选择和考虑。

为什么选择RabbitMQ?(技术选型)

选择RabbitMQ可以归结一下原因:

  1. 支持事务
  2. spring开发的,对spring支持好
  3. 开源

对比市面上常用的几种MQ:

ActiveMQRabbitMQKafkaRocketMQ
发布订阅支持支持支持支持
轮询分发支持支持支持/
公平分发/支持支持/
重发支持支持/支持
消息拉取/支持支持支持

对比得出:

  • 都支持持久化
  • 都支持发布订阅
  • 总之,RabbitMQ支持分发的策略最多。支持轮询、重发等

浅谈消息中间件协议

常见的消息中间件协议有:

  • OpenWire
  • AMQP(advanced message queuing protocol 高级消息队列协议)
  • MQTT
  • Kafka
  • OpenMessage

各种协议一般都是基于TCP进行改进,通过协议进行规范,以满足自己的需要。

而消息中间件为什么不用http协议?

  • 追求极致的性能,http请求报文头和响应报文头是比较复杂的。
  • 大部分情况下http是短连接的,不可靠。

RabbitMQ则是采用AMQP,其特点有:

  1. 支持分布式事务
  2. 支持消息的持久化
  3. 高性能和高可靠的消息处理优势

Kafka协议是基于TCP/IP的二进制协议,特点是:

  1. 结构简单
  2. 解析速度快
  3. 无事务支持
  4. 有持久化设计

MQTT:物联网体系支持

消息队列的模式

官方定义的模式7种,主要使用的有5种

  1. 简单模式。一个生产者+一个队列+一个消费者(使用默认交换器,没指定交换器那么发消息时routingkey写的就是队列名)
  2. 工作模式 work。一个生产者+一个队列+多个消费者(使用默认交换器)
    1. work模式-轮询模式(Round-Robin):一个消费者消费一条消息,按均分配。应答方式为自动应答,即autoAck = true
    2. work模式-公平分发:处理的快的处理的多,按劳分配。一定要改成手动应答,即消费者的autoAck = false,并且手动去应答。qos指标:表示每次从队列取多少条
  3. 发布订阅模式,使用fanout交换器,发送时不用指定routekey,无意义
  4. 路由模式 routing,只是在发布订阅模式上加了个路由key,相当于where routekey = xxx。要使用direct交换器,使用fanout毫无意义。相当于发布订阅+分类。
  5. 主题模式 topic。#没有或一级或多级,*有且只有一级
  6. RPC
  7. 确认模式

rabbitMQ的几种角色

  1. none
  2. management:只能查看自己相关结点信息
  3. policymaker:可以创建自己的
  4. monitoring:可以看别人的
  5. administrator:都可看可改

Spring整合rabbitMQ

Springboot整合rabbitmq十分方便,因为本来就是同一家公司的,步骤如下:

  1. 引依赖spring-boot-starter-amqp
  2. 写配置类创建交换器、队列以及他们的绑定关系。
    1. org.springframework.amqp.core.Queue
    2. org.springframework.amqp.core.FanoutExchange
    3. BindingBuilder.bind(smsQueue()).to(fanoutExchange());
  3. 写生产者
  4. 写消费者。
    1. 用@RabbitListenner(queues = {xxxqueue})注解
    2. @RabbitHandler

参考文献

  1. www.rabbitmq.com/getstarted.…
  2. RabbitMQ几种工作模式介绍