1. 详细介绍

什么是JMS MQ

全称:Java MessageService 中文:Java 消息服务。

JMS 是 Java 的一套 API 标准-最初的目的是为了使应用程序能够访问现有的 MOM 系 统(MOM 是 MessageOriented Middleware 的英文缩写-指的是利用高效可靠的消息传递机 制进行平台无关的数据交流-并基于数据通信来进行分布式系统的集成。) ;

后来被许多现有 的 MOM 供应商采用-并实现为 MOM 系统。【常见 MOM 系统包括 Apache 的 ActiveMQ、 阿里巴巴的 RocketMQ、IBM 的 MQSeries、Microsoft 的 MSMQ、BEA 的 RabbitMQ 等。 (并 非全部的 MOM 系统都遵循 JMS 规范)】

基于 JMS 实现的 MOM-又被称为 JMSProvider。

“消息”是在两台计算机间传送的数据单位。消息可以非常简单-例如只包含文本字符串; 也可以更复杂-可能包含嵌入对象。 消息被发送到队列中。

“消息队列”是在消息的传输过程中保存消息的容器。消息队列管 理器在将消息从它的源中继到它的目标时充当中间人。

队列的主要目的是提供路由并保证消 息的传递;如果发送消息时接收者不可用-消息队列会保留消息-直到可以成功地传递它。

消息队列的主要特点是异步处理-主要目的是减少请求响应时间和解耦。所以主要的使 用场景就是将比较耗时而且不需要即时(同步)返回结果的操作作为消息放入消息队列。同 时由于使用了消息队列-只要保证消息格式不变-消息的发送方和接收方并不需要彼此联系- 也不需要受对方的影响-即解耦和。如: 跨系统的异步通信-所有需要异步交互的地方都可以使用消息队列。就像我们除了打电 话(同步)以外-还需要发短信-发电子邮件(异步)的通讯方式。 多个应用之间的耦合-由于消息是平台无关和语言无关的-而且语义上也不再是函数调 用-因此更适合作为多个应用之间的松耦合的接口。基于消息队列的耦合-不需要发送方和 接收方同时在线。 在企业应用集成(EAI)中-文件传输-共享数据库-消息队列-远程过程调用都可以 作为集成的方法。 应用内的同步变异步-比如订单处理-就可以由前端应用将订单信息放到队列-后端应 用从队列里依次获得消息处理-高峰时的大量订单可以积压在队列里慢慢处理掉。由于同步 通常意味着阻塞-而大量线程的阻塞会降低计算机的性能。 消息驱动的架构(EDA)-系统分解为消息队列-和消息制造者和消息消费者-一个处 理流程可以根据需要拆成多个阶段(Stage) -阶段之间用队列连接起来-前一个阶段处理的 结果放入队列-后一个阶段从队列中获取消息继续处理。 应用需要更灵活的耦合方式-如发布订阅-比如可以指定路由规则。 跨局域网-甚至跨城市的通讯-比如北京机房与广州机房的应用程序的通信。

消息中间件应用场景

异步通信

有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制-允许用户把一个消息放入队列-但并不立即处理它。想向队列中放入多少消息就放多少-然后在需要的时候再去处理它们。

缓冲

在任何重要的系统中-都会有需要不同的处理时间的元素。消息队列通过一个缓冲层来帮助任务最高效率的执行-该缓冲有助于控制和优化数据流经过系统的速度。以调节系统响应时间。

解耦

降低工程间的强依赖程度-针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求-是极其困难的。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层-两边的处理过程都要实现这一接口-当应用发生变化时-可以独立的扩展或修改两边的处理过程-只要确保它们遵守同样的接口约束。

冗余

有些情况下-处理数据的过程会失败。除非数据被持久化-否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理-通过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中-在把一个消息从队列中删除之前-需要你的处理系统明确的指出该消息已经被处理完毕-从而确保你的数据被安全的保存直到你使用完毕。

扩展性

因为消息队列解耦了你的处理过程-所以增大消息入队和处理的频率是很容易的-只要另外增加处理过程即可。不需要改变代码、不需要调节参数。便于分布式扩容。

可恢复性

系统的一部分组件失效时-不会影响到整个系统。消息队列降低了进程间的耦合度-所以即使一个处理消息的进程挂掉-加入队列中的消息仍然可以在系统恢复后被处理。

顺序保证

在大多使用场景下-数据处理的顺序都很重要。大部分消息队列本来就是排序的-并且能保证数据会按照特定的顺序来处理。

过载保护

在访问量剧增的情况下-应用仍然需要继续发挥作用-但是这样的突发流量无法提取预知;如果以为了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力-而不会因为突发的超负荷的请求而完全崩溃。

数据流处理

分布式系统产生的海量数据流-如:业务日志、监控数据、用户行为等-针对这些数据流进行实时或批量采集汇总-然后进行大数据分析是当前互联网的必备技术-通过消息队列完成此类数据收集是最好的选择。

常用消息队列(ActiveMQ、RabbitMQ、RocketMQ、Kafka)比较

特性MQ

ActiveMQ

RabbitMQ

RocketMQ

Kafka

生产者消费者模式

支持

支持

支持

支持

发布订阅模式

支持

支持

支持

支持

请求回应模式

支持

支持

不支持

不支持

Api完备性

多语言支持

支持

支持

java

支持

单机吞吐量

万级

万级

万级

十万级

消息延迟

微秒级

毫秒级

毫秒级

可用性

高(主从)

高(主从)

非常高(分布式)

非常高(分布式)

消息丢失

理论上不会丢失

理论上不会丢失

文档的完备性

提供快速入门

社区活跃度

商业支持

商业云

商业云

JMS中的一些角色

Broker

消息服务器-作为server提供消息核心服务

provider

生产者

消息生产者是由会话创建的一个对象-用于把消息发送到一个目的地。

Consumer

消费者

消息消费者是由会话创建的一个对象-它用于接收发送到目的地的消息。消息的消费可以采用以下两种方法之一:

  • 同步消费。通过调用消费者的receive方法从目的地中显式提取消息。receive方法可以一直阻塞到消息到达。
  • 异步消费。客户可以为消费者注册一个消息监听器-以定义在消息到达时所采取的动作。
  • p2p

    基于点对点的消息模型

    消息生产者生产消息发送到 queue 中-然后消息消费者从 queue 中取出并且消费消息。 消息被消费以后-queue 中不再有存储-所以消息消费者不可能消费到已经被消费的消 息。 Queue 支持存在多个消费者-但是对一个消息而言-只会有一个消费者可以消费、其它 的则不能消费此消息了。 当消费者不存在时-消息会一直保存-直到有消费消费

    illustration

    pub/sub

    illustration

    基于订阅/发布的消息模型

    消息生产者(发布)将消息发布到 topic 中-同时有多个消息消费者(订阅)消费该消 息。 和点对点方式不同-发布到 topic 的消息会被所有订阅者消费。 当生产者发布消息-不管是否有消费者。都不会保存消息 一定要先有消息的消费者-后有消息的生产者。

    PTP 和 PUB/SUB 简单对

    1

    Topic

    Queue

    Publish Subscribe messaging 发布 订阅消息

    Point-to-Point 点对点

    有无状态

    topic 数据默认不落地-是无状态的。

    Queue 数据默认会在 mq 服 务器上以文件形式保存-比如 Active MQ 一 般 保 存 在 $AMQ_HOME\data\kahadb 下 面。也可以配置成 DB 存储。

    完整性保障

    并不保证 publisher 发布的每条数 据-Subscriber 都能接受到。

    Queue 保证每条数据都能 被 receiver 接收。消息不超时。

    消息是否会丢失

    一般来说 publisher 发布消息到某 一个 topic 时-只有正在监听该 topic 地址的 sub 能够接收到消息;如果没 有 sub 在监听-该 topic 就丢失了。

    Sender 发 送 消 息 到 目 标 Queue- receiver 可以异步接收这 个 Queue 上的消息。Queue 上的 消息如果暂时没有 receiver 来 取-也不会丢失。前提是消息不 超时。

    消息发布接 收策略

    一对多的消息发布接收策略-监 听同一个topic地址的多个sub都能收 到 publisher 发送的消息。Sub 接收完 通知 mq 服务器