ActiveMQ 基本概念

ActiveMQ是一种开源的基于JMS(Java Message Servie)规范的一种消息中间件的实现,提供了高可用、高性能、可伸缩性等。

为什么要用消息中间件

在分布式系统设计架构中,系统之间的偶尔是非常重要的,消息中间件可以用来解耦。RPC框架也可以用来解耦,但两个有不一样的地方:
RPC框架:
image.png
如上图所示,在RPC框架中,One应用通过网络直接调用Two应用,这就要保证Two应用是可用的,如果Two应用是不可用的,那这个调用就失败了。
消息中间件:
image.png
如上图所示,One应用把消息推送给消息中间件,Two应用再从消息中间件接收消息,在这个过程中,One应用和Two应用,是可以不知道对方的状态(比如是否不可用,用哪些语言),甚至不关心发送消息或者处理消息的是谁,这种情况下,两个应用的耦合度就不会那么高了。

应用场景

  • 注册后发送短信、邮件:发送短信和邮件,并不影响注册,可解耦
  • 两个耦合度不高的系统:比如A系统的日志通过mq保存到其他地方
  • 流量削峰:比如抢红包、秒杀

JMS

Java Message Service,JMS是是一个Java平台中关于面向消息中间件(MOM)的API,他并不是MOM,而只是一个API。
在对API进行标准化的过程中,JMS正式定义了以下几种概念和构件:

  • JMS客户端:100%java写的应用,用来接收和发送消息。
  • Non-JMS客户端:使用JMS提供商提供的本地API来接收发送消息。
  • JMS生产者:创建和发送消息的客户端应用。
  • JMS消费者:接收和处理消息的客户端应用。
  • JMS提供者:基于java对JMS的API实现,比如ActiveMQ。
  • JMS消息:JMS最基本的概念,通过JMS客户端来发送和接收。
  • JMS领域:两种消息传递的类型,点对点和发布订阅。
  • Administered Objects:对JMS对象进行配置。
  • 连接工厂:客户端使用连接工厂来创建与JMS提供者的连接。
  • 目的地:消息发送以及消息获取的地方。

JMS客户端

JMS定义了两种客户端,一个是JMS客户端和Non-JMS客户端。发送JMS消息的客户端叫做生产者,接收JMS消息的客户端叫消费者。

JMS消息

JMS消息包括三部分:头部(headers),属性(properties)和实际负载(payLoad)。

头部

头部提供了客户端和JMS提供者使用的消息元数据,每个消息头字段都有对应的set和get方法。

  • JMSDestination:对应Destination。
  • JMSDeliveryMode:1为非持久化,2为持久化,默认为2持久化。持久化后的消息不会丢失,也不会重复传递。虽然有存储的开销,但是带来了可靠性。
  • JMSExpiration:设置消息的过期时间,预防消息过期后还可以被传递。可以通过MessageProducer.setTimeToLive()设置当前这个生产者全局的过期时间,也可以通过MessageProducer.send()的timeToLive参数设置某个消息发送的过期时间。默认是0,意味着不过期。如果想设置10秒后过期,就赋值当前时间+1万毫秒。
  • JMSMessageID:以 ‘ID:’开头的唯一标识字符串,可以用于消息处理或消息中的历史用途存储机制。为了避免产生ID造成额外的开销,可以通过MessageProducer.setDisableMessageID()方法来关闭。
  • JMSPriority:优先级,0最低,9最高。
  • JMSTimestamp:消息生产者发送给消息提供者的时间。可以通过MessageProducer.setDisableMessageTimestamp()取消。
  • JMSCorrelationID:用于关联当前消息和之前的消息,它的值可以是与提供者相关的消息ID、与应用相关的字符串以及本地提供者的byte[]。前面两个都是字符串,用’ID:’是否开头来区分。
  • JMSReplyTo:通常用于request/reply,也就是说A发送给消息中间件,B消费后返回的消息,再发送给A。
  • JMSType:用于语义上标识消息类型
  • JMSRedelivered:消息已经发送,但是未被确认。
属性

属性是附加给客户端消息的可选字段,这是我们自定义的,如果消息头字段没有我们想要的话。
JMS提供了boolean、byte、double、float、int、long、object、short、string的属性设置类型。如图下所示:
image.png
另外JMS还提供了getPropertyNames()方法来回去自定义的属性,以及propertyExists()方法判断是否有设置自定义属性。

消息选择器

通过对消息头的消息进行过滤,使消费者对自己感兴趣的事件进行订阅。
image.png

实际负载

实际负载是消息的主体,包括TextMessage、StreamMessage、ObjectMessage、MapMessage、BytesMessage、BlobMessage。

JMS领域

JMS的消息传递,包括点对点和发布订阅

点对点

The point-to-point (PTP)点对点,类似于消息队列,可以同步或者异步的发送和接收消息。每个消息仅被发送一次,且仅消费一次。消费者可以通过 MessageConsumer.receive()同步接收队列的消息,也可以通过MessageConsumer.setMessageListener()异步接收队列的消息。如下图所示,消息生产者发送了一个消息,仅有一个消息消费者接收到了消息。
image.png

发布订阅

publish/subscribe (pub/sub) 发布订阅。消息生产者将消息发到topic中,消息消费者从topic读取,与点对点不同的是,消息可以被重复消费的,所以消息消费者可以有多个。如下图所示,消息生成发送了一个消息,5个消息消费者都进行了接收。
image.png
与点对点一样,消费者可以通过 MessageConsumer.receive()同步接收队列的消息,也可以通过MessageConsumer.setMessageListener()异步接收队列的消息。

连接工厂

在JMS中,通过ConnectionFactory 进行连接,由于每次创建连接比较消耗性能,所以跟数据库连接类似,采用了连接池的做法。

目的

Destination对象封装了消息发送和接收的消息提供者地址