消息队列都应用到了哪些实际的应用场景中?数组
1、再谈消息队列的应用场景服务器
一、异步处理:例如短信通知、终端状态推送、App推送、用户注册等网络
二、数据同部:业务数据推送同步并发
三、重试补偿:记帐失败重试异步
四、系统解耦:通信上下行、终端异常监控、分布式事件中心分布式
五、流量削峰:秒杀场景下的下单处理高并发
六、发布订阅:HSF的服务状态变化通知、分布式事件中心性能
七、高并发缓冲:日志服务、监控上报spa
可是,咱们对消息队列的底层技术和原理仍是不了解,那么咱们立刻开始吧。线程
2、消息队列的一些基本概念和简单原理
一、Broker
Broker的概念来自于Apache ActiveMQ,通俗的讲就是MQ的服务器。
二、消息的生产者、消费者
消息生产者Producer:发送消息到消息队列。
消息消费者Consumer:从消息队列接收消息。
三、点对点消息队列模型
消息生产者向一个特定的队列发送消息,消息消费者从该队列中接收消息;消息的生产者和消费者能够不一样时处于运行状态。每一个成功处理的消息都由消息消费者签收确认(Acknowledge)。如图:
四、发布订阅消息模型-Topic
发布订阅消息模型中,支持向一个特定的主题Topic发布消息,0个或多个订阅者接收来自这个主题的消息。这种情模型下,发布者和订阅者闭此不知道对方。实际操做过程当中,必须先订阅,再发送消息,然后接收订阅的消息,这个顺序必须保证。
五、消息的顺序性保证
基于Queue消息模型,利用FIFO先进先出的特性,能够保证消息的顺序性。
六、消息的ACK确认机制
即消息的Acknowledge确认机制
为了确保消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费者处理,发送一个ACK给消息队列,此时消息队列即可以删除这个 消息了。若是Consumer宕机/关闭,没有发送ACK,消息队列讲人为这个消息没有被处理,会将这个消息发送给其余的Consumer从新消息处理。
七、消息的持久化
消息的持久化,对于一些关键的核心业务来讲是很是重要的,启用消息持久化后,消息队列宕机重启后,消息而已从持久化存储恢复,消息不丢失,能够继续消费处理。
八、消息的同部和异步收发
同部:消息的收发支持同步收发的方式。
同时还有另外一种同步方式:同步收发场景下,消息生产者和消费者双向应答模式,例如:张三写封信松道邮局中转站,而后李四从中转站得到信,而后在写一份回执信,放到中转站,而后张三去取,固然张三写信的时候就得写明回信地址。
消息的接收若是以同步的方式(Pull)进行接收,如哦队列中为空,此时接收处于同步阻塞状态。会一直等待,直到消息的到达。
异步:消费的收发一样支持异步方式:异步发送 消息,不须要等待消息队列的接收确认;异步接收消息,以Push的方式触发消息消费者接收消息。
九、消息的事务支持
消息的收发处理支持事务,例如:在任务中心场景中,一次处理可能处理涉及多个消息的接收、处理,这处于同一个事务范围内,若是一个消息处理失败,事务回滚,消息从新回到队列中。
3、咱们对消息队列的实际使用
我在实际的项目中,使用过两种消息队列组件:
RabbitMQ:高可用、高可靠消息应用场景,例如记帐失败重试、通知服务,消息不容许丢
Kafka:高性能消息应用场景,例如日志、监控、消息容许丢失。
在此之上,咱们封装了消息应用中心,日志服务等核心组件和服务,那么,消息应用中心和日志都用到了消息队列什么技术?干活来了……
一、消息应用中心
消息应用中心(任务中心)使用了消息队列的异步处理、数据同步、重试补偿、系统解耦、流量削峰等特性。其中:消息应用中心(任务中心),支持RabbitMQ和Kafka两种消息通道,支持在任务元数据层面设置
任务:就是一个包含了任务执行上下文的消息,同时表明了异步处理
任务发送者(ITaskSender)发送任务:消息的生产者将任务消息发送到消息队列
任务类型:消息队列名称,例如:HaKeepAcco***Queue,充电补偿记帐队列
消息队列:任务的临时存储
任务中心:任务计中处理,消息消费者
任务处理完成:消息Ack确认
任务的多级重试:多个重试消息队列,HaSysTaskStore2Queue
二、日志组件
日志组件,使用了消息队列的高并发缓冲和发布订阅特性。其中:日志组件使用Kafka做为消息通道,由于Kafka的性能号,吞吐量大,能够容忍偶尔的消息数据丢失,日志组件使用发布订阅的消息模型,日志组件包含日志服务SDK和日志HSF服务,两者都是消息的生产者Producer,日志类型:消息的Topic主题。日志处理器:消息的消费者、Topic的订阅、日志数据处理(Hbase\ES\其余)
三、RPC服务状态变化通知
RPC服务状态变化通知,使用了消息队列的发布订阅特性,其中:RPC服务状态变化通知,使用RobbitMQ消息队列技术,使用发布订阅的消息模型,Topic:RPCServiceState。RPCService.Proxy:RPC服务状态变化消息的订阅者。RPC服务注册、发布:消息的生产者,发送RPC服务状态变化消息。
4、消息队列使用的最佳实践
一、RabbitMQ的连接,底层都是Socket连接,长链接 or 短连接?
RabbitMQ在建立每一个连接的同时,会自动建立一个监控线程来定时(默认60s)侦测连接的状态,若是连接断开,触发ConnectionShutdown事件。
用长链接,仍是用短链接?
发送端:建议使用短链接,用完即释放,避免长链接带来的端口占用,由于发送端无处不在,发送操做短而急促。
接收端:建议使用长链接,时刻接收处理消息,由于消息的接收消费比较集中,接收操做久而弥坚。
二、网络是有抖动的,链接的断开是正常的,如何应对?
发送端:发送失败重试
接收端:注册ConnectionShutdown事件同时捕获消息接收异常,从新创建链接,接收消费消息。
三、RabbitMQ Exchange(Topic)模式下带来的消息队列数量激增
只是建立了一个Exchange(Topic),为何会增长这么多Queue。觉得,每一个Topic的订阅都是绑定一个Queue用做消息的消费。
四、需求的演变,消息结构的改变,如何平滑过渡?
消息是byte[]数组,咱们将复杂对象消息二进制序列化。接收到消息后,咱们将二进制数组反序列化为实体类。当咱们的实体类消息体的结构发生变化后,由于受到二进制学历恶化处理的影响,致使没法反序列化。
解决方案:
消息体预留一些string类型的扩展字段。
消息队列版本化,支持多个版本的消息体。
五、Kafka Conusmer Group
同一个Topic的一条消息只能被同一个Group内的一个Consumer消费,多个Consumer Group可同时消费同一个消息。
六、消息的挤压
消息的挤压产生的缘由:消息接收消费的速率低,发送的速度>接收的速度。
消息积压后得影响:
消息大量积压后,当新得消费者链接上MQ并开始接收消息时,发送速率会大幅下降。消息队列集群得压力增长,大量得消息要持久化存储和同步。
如何减小消息挤压:快速消费消息,同时保持消息体不要过大。
此次的MQ相关知识先分享到这里。