消息队列之通信协议

2020-06-18  本文已影响0人  冰河winner

1、消息队列是什么

分布式系统中常用通讯模型主要是“请求-应答”模型和“发布-订阅”模型。前者常见如RPC通讯,常用HTTP REST或Dubbo等协议;后者多指消息队列通讯。

RPC大多属于请求-应答模式,也包括越来越多响应式范式,对于需要点对点交互、强事务保证和延迟敏感的服务/应用之间的通信,RPC是优于消息队列的。

消息队列(Message Queue,MQ)可以看做是一种异步RPC,把一次RPC变为两次或多次,进行内容转存,再在合适的时机投递出去。消息的发送者和接收者不需要在同一时间与消息队列进行交互,消息在被处理或被删除之前一直存储在队列上。

1.png

消息队列提供一个临时存储消息的轻量级缓存区,以及允许软件组件连接到队列以发送接受消息的的终端节点。这些消息通常较小,可以是请求、恢复、错误消息或明文消息等。要发送消息时,一个名为“生产者”的组件将消息添加到队列。消息将存储在队列中,直至名为“消费者”的另一组件检索该消息并执行相关操作。

许多生产者和消费者都可以使用队列,但一条信息只能有一组消费者处理一次。因此,这种消息收发模式通常称为一对一或点对点通信。如果消息需要由多个消费者进行处理,可以将将消息队列与发布/订阅结合起来使用。

2、消息队列协议

AMQPMQTTSTOMP是三种最常见、最流行的基于TCP/IP的消息传递协议。

2.1 AMQP

AMQP,即高级消息队列协议(Advanced Message Queuing Protocol),一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。

核心角色如下:

生产者发送消息时,必须指定消息要被路由到哪些个消息队列中。当消息到消息队列中,消息队列会尝试将消息传给消费者,如果失败,消息队列会存储消息并等待消费者。如果没有消费者,消息队列将选择性的将消息返回给生产者。如果消息别消费掉,消息队列会删除消息,删除的过程或者是及时的,或者是等到消费者消费结果后才删除的。

RabbitMQ是AMQP消息队列最有名的开源实现,当然RabbitMQ同时还可以通过插件支持STOMP、MQTT等协议接入。Kafka、RocketMQ均使用自定义的协议。

2.2 MQTT

MQTT,即消息队列遥测传输(Message Queuing Telemetry Transport)。由IBM开发,现在被广泛用于物联网公司。因为他的特点就是轻量,简单,开放和易于实现。所以它常用于很多计算能力有限、带宽低、网络不可靠的远程通信应用场景。

核心角色如下:

MQTT协议是通过交换预定义的MQTT控制报文来通信的,控制报文内容由三部分组成:固定报头,可变报头和消息体。固定报头通过标识不同位的值来确定报文类型,包括发布订阅的一些完成状态等;可变报头的内容根据控制报文类型不同而不同,常作为包的标识符;消息体也是根据不同的消息类型有着不同的内容。

MQTT协议中,客户端和服务端是通过请求-应答模式通信的。客户端发送一条控制报文数据给服务器,服务器再发送一条控制报文数据给客户端。

MQTT在发布消息时,有三种Qos等级:

至多一次等级最低,客户端只需要将消息发出去即可,这种等级很低,用于消息不重要但特别多,为了减轻通信压力,就不顾质量,只看数量了。

至少一次等级中等,客户端要保证发出去的消息至少一次被服务端接收到,所以要收到服务端的回应,否则一直发,这种等级一般用于服务端有幂等处理,所以不怕重复消费,还要保证消息不会丢失。

只有一次等级最高,客户端先发消息过去,然后本地记录一个我已发送,但不确定你是否收到的状态,然后服务端接收到消息后,回给客户端一个我已接收的报文,同时服务端记录一个我不确定你知不知道我已接收的状态,然后客户端收到这个已接收的消息后,就确定服务端收到这个消息了,于是把自己本地记录的已发送未确定的状态删除,同时再给客户端发送一个我已经知道你收到的报文,服务端收到这个报文,也会把自己之前记录的状态删掉,整个一条报文只有一次的通信才算完成,这种等级就比较严格了,但质量上去了,相对低等级的,数量就会相对小些,但可靠就是王道,不多不少才是最好的。

只有一次的发送和确定,其实思想和三次握手差不多,都是两端互相确认的过程,所以会一来一回的。如果传输过程中出现丢包,都会由发送者重发上一条消息。

2.3 STOMP

STOMP,即流文本定向消息协议(Streaming Text Orientated Messaging Protocal),是一个相对简单的文本消息传输协议,主要特点就是简单易懂,没有特别多的套路。

核心角色如下:

ActiveMQ以及它的下一代实现Apache Apollo,是STOMP协议的典型实现。

3、JMS

3.1 概述

JMS(Java MessageService)实际上是一套JAVA API接口,是由Sun公司早期提出的消息标准,旨在为java应用提供统一的消息操作,包括create、send、receive等。

严格来讲,JMS并不属于消息协议,而是一种规范,是对AMQP,MQTT,STOMP等协议更高一层的抽象。从使用角度看,JMS和JDBC担任差不多的角色,用户都是根据相应的接口可以和实现了JMS的服务进行通信,进行相关的操作。

JMS通常包含如下一些角色:

消息如何从producer端达到consumer端由message-routing来决定。在JMS中,消息路由非常简单,由producer和consumer链接到同一个queue(p2p)或者topic(pub/sub)来实现消息的路由。JMSconsumer同时支持message selector(消息选择器),通过消息选择器,consumer可以只消费那些通过了selector筛选的消息。

3.2 通信模型

JMS具有两种通信模式:

在JMS API出现之前,大部分产品使用“点对点”和“发布/订阅”中的任一方式来进行消息通讯。JMS定义了这两种消息发送模型的规范,它们相互独立。任何JMS的提供者可以实现其中的一种或两种模型,这是它们自己的选择。JMS规范提供了通用接口保证我们基于JMS API编写的程序适用于任何一种模型。

3.2.1 点对点模型

2.png

在点对点通信模式中,应用程序由消息队列,发送方,接收方组成。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。

3.2.2 发布/订阅模型

3.png

在发布/订阅消息模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端。该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。

3.3 接收消息

在JMS中,消息的产生和消息是异步的。对于消费来说,JMS的消息者可以通过两种方式来消费消息。

3.4 编程模型

4.png
上一篇下一篇

猜你喜欢

热点阅读