一、消息中间件
消息中间件即Message-oriented middleware(MOM),消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。
通过提供消息传递和消息排队模型,消息中间件可以在分布式环境下扩展进程间的通信。
消息中间件可以即支持同步方式,又支持异步方式。
异步中间件比同步中间件具有更强的容错性,在系统故障时可以保证消息的正常传输。异步中间件技术又分为两类:广播方式和发布/订阅方式。
消息中间件应用主要有两个优点:异步和解耦。
1.AMQP规范
AMQP 是 Advanced Message Queuing Protocol,即高级消息队列协议。AMQP不是一个具体的消息队列实现,而 是一个标准化的消息中间件协议。目标是让不同语言,不同系统的应用互相通信,并提供一个简单统一的模型和编程接口。
目前主流的ActiveMQ和RabbitMQ都支持AMQP协议。
AMQP相关的角色和职责
Producer 消息生产者
一个给exchange发送消息的程序,发送方式大致是:它首先创建一个空消息,然后填上内容、路由KEY,最后发送给exchange
Routing Key 消息特征
一个字符串,exchange用之来决定应该该消息投递给哪个queue。(开始时queue已向exchange绑定它所关心消息的routingKey)
Exchange 交换器
接收来自producers的消息,并根据该消息的routingKey,将该消息投递到正确的queues
Binding 绑定操作
前期将queue所想要的消息特征告诉exchange。Exchange以后收到消息,就按照这个规则来投递
Queue 消息容器
在MQ server(实现为broker方式)里面的queue,持有Consumer想要的消息
Consumer 消息接收者
从MQ server得到想要的消息,它负责创建、主动订阅、共享、使用、破坏queue和binding
2.JMS规范
JMS是Java平台的一部分,是一种应用于异步消息传递的标准API,JMS可以允许不同应用、不同模块之间实现可靠、异步数据通信。
在JMS中,支持两种消息模型,点对点(Point-to-point)和发布-订阅(Publish and subscribe),
这两种模式分别对应于JMS中的两种消息目标(Message Destination):队列及主题(queue/topic)。
在点对点模型中,每个消息都有一个发送者和一个接收者,消息中介(broker)收到发送者的消息,会将消息放入队列中,而接收者请求并接收队列中的一条消息后,这条消息就会从队列中删除。
消息队列中的每条消息只能投递给一个接收者,但并不意味着只能使用一个接收者从队列中取消息,根据业务需要,可以使用多个接收者同时从队列中请求消息,分担处理压力。
但是需要注意的是,单个接收者收到的消息是按照发送顺序的,多个接收者因为多线程的关系,并不能保证收到的消息一定是原序的。
在发布-订阅模式中,消息会发送给一个主题,但是与点对点模式不同的是消息不再只被投递给一个接收者,而是所有此主题的订阅者都会收到该消息。
二、JMS规范实现
JMS即Java消息服务(Java Message Service),JMS是一个基于Java平台面向消息中间件(MOM)的API,用于在两个应用程序之间,
或分布式系统中发送消息,进行异步通信。
Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。
JMS是类似于JDBC(Java Database Connectivity),并不局限于某个具体消息中间件,
JDBC 是可以用来访问许多不同关系数据库的 API,
而 JMS 则提供同样与中间件无关的访问方法,以访问消息收发服务。
1.JMS对象模型
ConnectionFactory:
连接工厂,JMS 用它创建连接Connection,一般设为单例模式,
一旦创建,就一直运行在应用容器内,客户端使用JNDI查找连接工厂,然后利用连接工厂创建一个JMS连接。
Connection:
JMS连接表示JMS客户端和服务器端之间的一个活动的连接,是由客户端通过调用连接工厂的方法建立的。
Session:
JMS会话表示JMS客户与JMS服务器之间的会话状态。JMS会话建立在JMS连接上,表示客户与服务器之间的一个会话线程。
Destination:
消息的目的,包括队列(PTP),主题(Pub/Sub)。
Message Producer和Message Consumer:
生产者和消费者对象由Session对象创建,用于发送和接收消息。
Message:
JMS 消息由以下几部分组成:消息头,属性,消息体。
消息头(header):JMS消息头包含了许多字段,它们是消息发送后由JMS提供者或消息发送者产生,用来表示消息、设置优先权和失效时间等等,并且为消息确定路由Routing。
属性(property):由消息发送者产生,用来添加删除消息头以外的附加信息。
消息体(body):由消息发送者产生,JMS中定义了5种消息体:ByteMessage、MapMessage、ObjectMessage、StreamMessage和TextMessage。
2.两种消息传递模型
(1)点对点模型(Point-to-Point)
点对点模型用于消息生产者和消息消费者之间点到点的通信。消息生产者将消息发动到由某个名字标识的特定消费者。这个名字实际上对应于消息服务中的一个队列(Queue),在消息传动给消费者之前它被存储在这个队列中。队列可以是持久的,以保证在消息服务出现故障时仍然能够传递消息。
(2)发布-订阅模型(Publish/Subscribe)
发布-订阅模型用称为主题(topic)的内容分层结构代替了PTP模型中的惟一目的地,
发送应用程序发布自己的消息,指出消息描述的是有关分层结构中的一个主题的信息。希望接收这些消息的应用程序订阅了这个主题。订阅包含子主题的分层结构中的主题的订阅者可以接收该主题和其子主题发表的所有消息
三、消息队列的主要开源实现
-
ActiveMQ
ActiveMQ 是Apache出品,目前非常流行的开源消息中间件。ActiveMQ 支持JMS规范,同样也支持AMQP协议。
在下面的博客里,将会较深入的学习ActiveMQ的设计和应用。
-
RabbitMQ
RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP) 的开源实现,开发语言是以高性能、健壮以及可伸缩性出名的 Erlang 。
-
RocketMQ
RocketMQ 是阿里的一款分布式、队列模型的消息中间件。
项目地址 https://github.com/alibaba/RocketMQ
软件文档 https://github.com/alibaba/RocketMQ/wiki
-
三种消息队列的比较
ActiveMQ
优点:成熟的产品,已经在很多公司得到应用(非大规模场景)。有较多的文档。 各种协议支持较好,有多重语言的成熟的客户端;
缺点:根据其他用户反馈,会出莫名其妙的问题,会丢失消息。其重心放到activemq6.0产品—apollo上去了,目前社区不活跃,且对 5.x 维护
较少;Activemq 不适合用于上千个队列的应用场景
RabbitMQ
优点:由于erlang语言的特性, mq性能较好;管理界面较丰富,在互联网公司也有较大规模的应用;支持 amqp 系诶,有多中语言且支持amqp 的客户端可用
缺点:erlang语言难度较大。集群不支持动态扩展。
RocketMq
优点:模型简单,接口易用(JMS的接口很多场合并不太实用)。 在阿里大规模应用。 目前支付宝中的余额宝等新兴产品均使用rocketmq。
集群规模大概在50 台左右,单日处理消息上百亿;性能非常好,可以大量堆积消息在broker 中;支持多种消费,包括集群消费、广播消费等。 开发度较活跃,版本更新很快。
缺点:产品较新,文档比较缺乏。没有在 mq核心中去实现JMS 等接口,对已有系统而言不能兼容。阿里内部还有一套未开源的 MQ API,这一层 API可以将上层应用和下层 MQ 的实现解耦。