自己写的网上商城项目中使用了ActiveMQ,虽然相比于RabbitMQ,kafka,RocketMQ等相比,ActiveMQ可能性能方面不是最好的选择,不过消息队列其实原理区别不大,这里对学过的关于消息队列的知识进行一下总结,并结合自己面试中关于这方面遇到的问题做一个整理,为后面秋招找工作做准备。这一篇主要介绍一下JMS,ActiveMQ安装及其常用接口,两种队列模式,如何集成到Spring项目,面试总结等。
JMS
Java Message Service,Java消息服务应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个程序之间,或分布式系统中发送消息,进行异步通信,JMS是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。这是比较详细的关于JMS的定义,而比较直观的说,JMS是一组消息服务的API,也就是说JMS只有接口,其具体实现类交给了各种MOM厂家来做。
JMS使用场景,应用程序A部署在北京,应用程序B部署在上海,每当A触发某个事件之后,B向获取A中的一些信息,也可能有很多个B都想获取A中的信息。这种情况下,Java提供了最佳的解决方案-JMS。JMS同样适用于基于事件的应用程序,如聊天服务,他需要一种发布事件机制向所有与服务器连接的客户端发送消息。JMS与RMI不同,不需要接受者在线。也就是服务器发送完消息,这个事件就与他无关了。
JMS的优势:
- 异步,JMS天生就是异步的,客户端获取消息的时候,不需要主动发送请求,消息会自动发送给可用的客户端。
- 可靠,JMS保证消息只会被递送一次。大家都遇到过重复创建消息的问题,JMS可以帮你避免这个问题,但是不能杜绝,需要MOM厂家来做更加完备的机制来改善。
JMS常用的一些概念:
- Provider/MessageProvider:生产者
- Consumer/MessageConsumer:消费者
- PTP:Point To Point,点对点通信消息模型
- Pub/Sub:Publish/Subscribe,发布订阅消息模型
- Queue:队列,目标类型之一,和PTP结合
- Topic:主题,目标类型之一,和Pub/Sub结合
- ConnectionFactory:连接工厂,JMS用它创建连接
- Connnection:JMS Client到JMS Provider的连接
- Destination:消息目的地,由Session创建
- Session:会话,由Connection创建,实质上就是发送、接受消息的一个线程,因此生产者、消费者都是Session创建的
ActiveMQ简介
ActiveMQ是Apache出品的,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE1.4规范的JMS Provider实现,JMS上面已经有了简单的介绍。
ActiveMQ的特点:
- 多种语言和协议编写客户端,语言包括Java、C、C++、C#、Ruby、Perl、Python、PHP,协议包括OpenWire、Stomp、REST、WS Notification、XMPP、AMQP
- 完全支持JMS1.1和J2EE1.4规范
- 对Spring的支持,使得ActiveMQ集成到Spring里面很方便
- 支持多种传送协议:in-VM、TCP、SSL、NIO、UDP、JGroups、JXTA
- 支持通过JDBC和journal提供高速的消息持久化
- 从设计上保证了高性能的集群,客户端-服务器点对点
- 支持Ajax
- 支持与Axis的整合
ActiveMQ的消息形式
点对点,也就是一个省车按着对一个消费者的一对一
发布/订阅模式,一个生产者产生消息并进行发送后,可以由多个消费者进行接收
JMS中定义了五种不同的消息正文格式以及调用的消息信息,允许你发送并接收以一些不同形式的数据:
* StreamMessage --- 数据流
* MapMessage --- key-value
* TextMessage --- 字符串
* ObjectMessage --- 序列化的Java对象
* BytesMessage --- 一个字节的数据流
ActiveMQ的安装
- activemq.apache.org下载ActiveMQ
- 解压缩
- 启动, ./activemq start, 关闭 ./activemq stop, 查看状态 ./activemq status
后台管理页面:http://192.168.25.168:8161/admin, 用户名admin,密码admin
ActiveMQ的使用
添加jar包
|
|
使用Queue形式的消息队列
Producer
|
|
可以看出生产者和消费者之间传递的对象,由三个主要部分构成:消息头+消息属性+消息体。当然创建过程中也可以对消息进行持久化的选择等配置。
Consumer
|
|
注释基本解释清楚了基本的流程,唯一要注意的是接收消息的时候,我们先查看setMessageListener这个方法,其接口定义如下:
|
|
也就是说需要传入一个实现了MessageListener接口的对象,而MessageListener接口如下只有一个onMessage方法:
|
|
采用匿名类的方法来对test-Queue队列进行监控,只要有消息进来,就立即执行onMessage方法。
Topic模式
Provider
|
|
和队列模式相比,只是由session生成的消息队列模式编程了订阅发布模式,其他完全一样。
Consumer
|
|
ActiveMQ在Spring中的使用
上一节介绍的在项目中直接使用消息队列的方式,可以看出存在很大的重复代码,而且步骤很多,将ActiveMQ整合到Spring中可以大大改善这两个问题。
- 引入JMS相关jar包
|
|
- 配置ActiveMQ整合Spring,配置ConnectionFactory
|
|
- 配置生产者,使用JMSTemplate对象,发送消息
|
|
- 配置Destination
|
|
- 完整的配置文件:
|
|
测试代码
- 发送消息,步骤注释中写的很清楚了,
|
|
- 接收消息
由于项目中使用ActiveMQ实现索引库和数据库的同步,为了接收ActiveMQ的消息,需要创建一个MessageListener实现类。
|
|
然后在Spring中整合ActiveMQ的消息监听器
|
|
测试代码:
|
|