ActiveMQ-为何须要消息中间件?

消息中间件的优点

UNIX的进程间通讯就开始运用消息队列技术,一个进程将数据写入某个特定的队列中,其它进程能够读取队列中的数据,从而实现异步通讯。对于现在的分布式系统,消息队列已经演变为独立的消息中间件产品,相比于RPC同步通讯的方式来讲有几个明显的优点:编程

  • 低耦合,无论是程序仍是模块之间,使用消息中间件进行间接通讯。
  • 消息的顺序性,消息队列能够保证消息的先进先出。
  • 消息可靠传输,持久化的存储使得消息只有在被消费以后才会删除。
  • 异步通讯能力,相对于RPC来讲,异步通讯使得生产者和消费者得以充分执行本身的逻辑而无需等待。
  • 缓冲能力,消息中间件像是一个巨大的蓄水池,将高峰期大量的请求存储下来慢慢交给后台进行处理,对于秒杀业务来讲尤其重要。

可是异步通讯也存在程序设计和编程方面的复杂,同时对于实时性要求较高的业务也不能采用异步通讯,因此要根据业务具体分析。架构

J2EE和JEE是什么?

J2EE全称是Java to Enterprise Edition,是一套企业级技术规范,包含:JMS Servlet JSP EJB JPA 等。J2EE发展到1.5版本更名为JEE5,因此JEE是J2EE规范的延续。 并发

消息中间件的发展历程

  • J2EE时代,消息中间件强调企业级特性,好比消息持久化和事务性要求,所有遵循JMS规范。典型的ActiveMQ、HornetQ,后者如今已经发展成ActiveMQ Artemis子项目,这代表在Java/JEE领域ActiveMQ会继续发挥不可替代的做用。           
  • 后Java时代,随着消息中间件协议AMQP(Advanced Message Queuing Protocol)的诞生,最知名的AMQP消息中间件产品RabbitMQ也随之诞生,RabbitMQ基于Erlang开发,2007年诞生至今已经称为最流行的开源消息中间件产品,ActiveMQ于2013年也开始支持AMQP协议,后来Apache还推出了ActiveMQ Apollo的新项目,也实现了包括AMQP在内的多种协议。
  • 互联网时代,设计思路上采用分布式系统设计理念,以LinkedIn开源的Kafka为表明,Kafka使用Scala编写,因为良好的水平扩展能力和高性能被普遍采用,同时诞生了一些高仿的相似产品如搜狐的Jafka,阿里的RocketMQ等。              

 JMS是什么?

JMS Java Message Service Java消息服务是J2EE架构中针对消息中间件的一组规范。JMS规范定义了Java中访问消息中间件的接口,但没有给予实现,具体实现交给消息中间件,称为JMS Provider,如ActiveMQ就是一个JMS Provider。简单说,没有实现这些接口的消息中间件就不能归入J2EE(JEE)架构,Java程序也没法与其进行交互。异步

JMS的两种消息传送模型

JMS支持两种消息传送模型:点对点消息通讯模型和发布订阅模型。分布式

  • 点对点(PTP)消息通讯模型也可称之为队列模式,特定的一条消息只能被一个消费者消费。生产者将消息发送到指定的Queue当中,Broker(中间件)针对消息是否须要持久化进行持久化存储后通知消费者进行处理,消费者处理完毕后发送一个回执(Acknowledge)给Broker,Broker认为该消息已被正常消费,因而从持久化存储中删除该条消息。回执的发送逻辑内嵌在MQ的API中,无需主动调用。消费者一般能够经过两种方式获取新消息:PUSH和PULL。PUSH方式,由MQ收到消息后主动调用消费者的新消息通知接口,须要消耗MQ宝贵的线程资源,同时消费者只能被动等待消息通知;PULL方式,由消费者轮询调用MQ API去获取新消息,对应于ActiveMQ中的方法为consumer.receive(),不消耗MQ线程,消费者更加主动,虽然消费者的处理逻辑变得稍稍复杂。两种方式的根本区别在于线程消耗问题,因为MQ的线程资源相对客户端更加宝贵,PUSH方式会占用MQ过多的线程从而难以适应高并发的消息场景。同时当某一消费者离线一段时间再次上线后,大量积压消息处理会消耗大量MQ线程从而拖累其它消费者的消息处理,因此PULL方式相对来讲更好。Kafka已经抛弃了PUSH模式,全面拥抱PULL模式。

  • 发布/订阅模式(Pub/Sub)也可称之为主题模式,特定的一条消息能够被多个消费者所接收,只要消费者订阅了某个主题。消息生产者(发布者)将消息发送到某个称为主题(Topic)的虚拟通道中,Topic能够被多个消费者订阅,所以该模式相似于广播的方式。发布/订阅模式采用PUSH的方式传送消息,Subscriber只需保持在线便可。Subscriber分为临时性的和持久性的,当Sub离线时,MQ会为持久性的Sub持久化消息,当Sub恢复时会从新收到消息。可是既然采用Pub/Sub模式就代表容许部分消费者接收不到消息,因此一般会采用临时性的Subscriber而不是持久性的。