本文总结下ActiveMQ的核心功能,涉及一些概念和API。
一. Jms生产者Demo
先上一个生产者的小demo,然后围绕demo展开:
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce {
public static final String ACTIVEMQ_URL = "tcp://192.168.17.101:61616";
public static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException {
//创建连接工厂,按照给定的url地址,使用默认用户名和密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//通过连接工厂获取连接,并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//创建会话session,true开启事务,false不开启事务
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//创建目的地,是队列还是topic
Queue queue = session.createQueue(QUEUE_NAME);
//创建消息的生产者
MessageProducer producer = session.createProducer(queue);
//持久化模式设置
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
try {
//生产3条消息到队列
for (int i = 1; i <= 3; i++) {
//创建消息
TextMessage textMessage = session.createTextMessage("msg--" + i);
//使用生产者发送消息
producer.send(textMessage);
}
session.commit();
} catch (JMSException e) {
//异常情况回滚提交
session.rollback();
} finally {
//关闭资源
producer.close();
//如果上边开启事务,那么这里要提交,不然消息不进入队列
session.close();
connection.close();
}
System.out.println("发布消息到队列完成!");
}
}
上述是ActiveMQ的一种生产者的原生标准实现,生产3个消息到队列Queue中(或者主题Topic中),并且使用了事务模式。
本demo使用了JMS包,下面先总结下JMS。
二. JMS介绍
1.jms是什么
上述demo中使用了javax.jms.包中的内容,比如Connection/Session/Queue/MessageProducer/TextMessage等。JMS(Java Message Service),java消息服务,是JavaEE规范中的一个模块,制定了消息接收发送的一套标准规范,其中落地产品有很多(各种MQ),ActiveMQ就是其中一款落地产品,它完全遵守了JMS规范。
JMS提供了一套API,为标准消息协议和消息服务提供了一组接口,包括创建,发送,读取消息等。
2.jms组成的四大元素
- jms peovider :实现jms接口和规范的消息中间件,也就是MQ服务器;
- jms producer :消息生产者,创建和发送jms消息的客户端应用;
- jms consumer :消息消费者,接收和处理jms消息的客户端应用;
- jms message :发送和被接受的消息,包含消息头,消息体,消息属性;
3.jms 消息头
列举几个比较重要参数:
- JMSDestination :消息发送的目的地,主要指Queue还是Topic;Message接口提供了setJMSDestination方法;
- JMSDeliveryMode :设置持久化或者非持久化模式,非持久化模式下,MQ宕机,消息丢失,但是持久化模式不会丢失;
- JMSExpiration :设置消息过期时间,过期后会清除,默认是永不过期;
- JMSPriority :消息优先级,包含0-9是个级别,0-4是普通消息,5-9是加急消息,默认是4。JMS规范不要求MQ严格按照这个优先级顺序发送,但是要保证5-9的早于0-4的。
- JMSMessageID :唯一识别每个消息的标识,由MQ产生或者自己设定;
以上参数可以针对每条消息单独设置,也可以在send方法中统一设置。
4.消息体
消息体封装具体的消息数据,有多种类型格式,消息发送方和接收方的格式必须保持一致。
5种消息体格式:
- TextMessage :普通字符串,包含一个string;
- MapMessage :map类型,其中key为String类型,
- BytesMessage :二进制数组消息,包含一个byte[];
- StreamMessage :java数据流消息,用标准流来顺序填充和读取;
- ObjectMessage :对象消息,包含一个可序列话的java对象;
5.消息属性
识别,去重,重点标注等操作。
接口方法:
setStringProperty(String name, String value);
除此之外,还有setIntProperty等类型;需要注意的是,生产者与消费者的类型要保持一致。
三. 消息的持久化
jms消息默认是持久化的,可以通过JMS接口的如下方法设置持久与非持久:
void setDeliveryMode(int deliveryMode) throws JMSException;
public interface DeliveryMode {
//非持久
static final int NON_PERSISTENT = 1;
//持久
static final int PERSISTENT = 2;
}
非持久模式下,MQ如果宕机再启动,消息会丢失;持久化模式下,消息只要没消费掉,不会丢失。
四. 消息事务
1.生产者事务
文章开头的demo中,有如下内容:
//创建会话session,true开启事务,false不开启事务
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
第一个参数,true表示开启事务;false表示关闭事务;
开启了事务模式,那么就需要提交事务:
session.commit();
提交事务之前,消息不进入队列;只有提交后,消息才进入队列,消费者才能消费到。
2.消费者事务
消费者的事务使用代码和生产者一样。
消费者中,要注意commit,否则消费者会重复消费消息,消息一直在队列中消费不掉;只有提交事务后,才能被消费掉。
五. 消息签收
签收针对的是消费者,在消费者中,一般也会有如下代码:
//创建会话session,true开启事务,false不开启事务
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
其中,第二个参数是签收模式。在非事务模式下,共有如下几种类型:
-
Session.AUTO_ACKNOWLEDGE = 1; //自动签收,默认就是这种方式;在这种模式下,消费者会自动签收消息,也就是在拿到消息时,就默认签收了,不用在调用方法进行签收;
-
Session.CLIENT_ACKNOWLEDGE = 2; //手动签收,在这种模式下,消费者拿到消息后,需要使用如下方法进行手动签收,
textMessage.acknowledge ();
,否则,消息会残留在消息队列中,导致重复消费。 -
Session.DUPS_OK_ACKNOWLEDGE = 3; //允许重复签收,这种模式基本不使用。
注意,上述模式是针对非事务模式的;
如果在事务模式下,那么签收模式会失效,即使配置的是手动签收,在事务模式下,也会被自动签收。
六.传输协议种类
Demo中,使用了如下连接,可以发现,使用的的是tcp协议,
public static final String ACTIVEMQ_URL = "tcp://192.168.17.101:61616";
除了此种协议,ActiveMQ还支持其他类型协议:
1.transmission Control Protocol(TCP)
tcp是默认使用的协议,端口61616;
使用格式:tcp://hostname:port?key=value ,key和value可以不添加,具体内容有:
全部内容看官方文档:
http://activemq.apache.org/tcp-transport-reference
2.New I/O API Protocol (NIO)
nio基于tcp协议,进行了扩展和优化,比tcp协议具有更好的性能,实际生产中,也大多使用此种协议。
要使用此种模式,需要修改ActiveMQ的配置文件:conf / activemq.xml ,增加
<transportConnector name="nio" uri="nio://0.0.0.0:61616"/>
使用格式:nio://hostname:port?key=value ,其中key和value同tcp配置。
具体参考官方文档:
http://activemq.apache.org/configuring-version-5-transports.html
auto模式
从5.13.0版本开始,activemaq支持auto自动模式,可以从多种类型的协议中自动探测最终使用哪种协议。
官方文档:http://activemq.apache.org/auto
3.AMQP 协议
4.stomp协议
5.Secure Sockets Layer Protocol (SSL)安全连接
6. mqtt 协议
7. ws 协议
上述其他协议使用不多,具体看官方文档:
http://activemq.apache.org/configuring-version-5-transports.html