JMS是一个用于提供消息服务的技术规范,它制定了在整个消息服务提供过程中的所有数据结构和交互流程。而MQ则是消息队列服务,是面向消息中间件(MOM)的最终实现,是真正的消息服务提供者。MQ的实现可以基于JMS,也可以基于其他规范或标准,其中ActiveMQ就是基于JMS规范实现的消息队列。
一:
在指定机器M(ip加端口)安装AMQ:解压下载包并运行解压目录下的activemq.bat即可
(可在conf下的activemq.xml和users.properties中分别修改端口号和用户名,密码)
控制台:http://localhost:8161/admin
二:客户端依赖conf文件夹同级的jar(对AMQ服务来说,生产者和消费者都是客户端)
三:1.生产者和消费者连接M
2.生产者和消费者创建同名的队列/主题,生产者将队列/主题发往M,消费者从M获取。
例:
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class SendMQ {
public static final String userName = "testName";
public static final String password = "testPassword";
public static final String brokerUrl = "tcp://localhost:aaaaaaaaaaa";
public static final String queueName = "queueNameTest";
public static void main(String[] args) throws JMSException{
try{
//创建连接工厂(参数不含重试策略时:最大重试次数6,延迟1秒重发)
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:8888");
//创建连接
Connection connection = connectionFactory.createConnection();
//启动连接
connection.start();
//创建会话(所谓的会话就是一次连接而已)
/*如果事务被设置为true,那么会话将使用一个本地事务,该事务随后可能通过调用会话的commit或rollback方法被提交或回滚。参数确认模式被忽略。
如果事务设置为false,则会话将不进行事务处理。在这种情况下,参数确认模组用于指定如何确认会话接收到的消息。允许的值是会话。CLIENT_ACKNOWLEDGE、会话。AUTO_ACKNOWLEDGE Session.DUPS_OK_ACKNOWLEDGE*/
Session session = connection.createSession(true,Session.AUTO_ACKNOWLEDGE);
//以目的地(队列)为参数创建发布者(先创建目的地/消费地址) 生产者设置持久化模式时AMQ服务broker会将消息先存在磁盘再转发给订阅者
Destination destination = session.createTopic(queueName);
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//往队列发送消息
for(int i=0;i<2;i++) {
TextMessage messsage = session.createTextMessage("消息" + i);
producer.send(messsage);
}
//提交事务
session.commit();
//关闭连接
connection.close();}
catch(Exception e){
System.out.println(e);
}
}
}
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class ReceiveAMQ {
public static void main(String[] args)throws JMSException{
//创建连接工厂(参数不含重试策略时:最大重试次数6,延迟1秒重发)
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:8888");
//创建连接 是否需要制定ip??
Connection connection = connectionFactory.createConnection();
//开启连接
connection.start();
//创建会话(所谓的会话就是一次连接而已)
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//创建消费者
Destination destination = session.createTopic("queueNameTest");
MessageConsumer consumer = session.createConsumer(destination);
while(true) {
TextMessage message = (TextMessage) consumer.receive(2000);
System.out.println("接收——"+message);
}
}
}
四:关于重发策略和死信策略:
重发策略:创建连接工厂时用参数配置(重发次数,重发延迟时间(初始重发延迟时间为0生效)等),不配则见代码处注释
死信策略:在activemq.xml中的<destinationPolicy>中进行配置(持久消息模式可在代码中用生产者配置)
过期时间配置:
1)message过期则客户端不能接收
2)ttlCeiling:表示过期时间上限(程序写的过期时间不能超过此时间,超过则以此时间为准)
3)zeroExpirationOverride:表示过期时间(给未分配过期时间的消息分配过期时间)
<broker>
<plugins>
<!-- 86,400,000ms = 1 day -->
<timeStampingBrokerPluginttlCeiling="30000" zeroExpirationOverride="30000"/>
</plugins>
</broker>
消息过期后会进入死信队列,如不想抛弃死信队列,默认进入ACTIVEMQ.DLQ队列,且不会自动清除;对于过期的消息进入死信队列还有一些可选的策略:放入各自的死信通道、保存在一个共享的队列(默认),且可以设置是否将过期消息放入队列的开关以及死信队列消息过期时间。
1)直接抛弃死信队列
AcitveMQ提供了一个便捷的插件:DiscardingDLQBrokerPlugin,来抛弃DeadLetter。如果开发者不需要关心DeadLetter,可以使用此策略。
配置示例
<broker>
...
<plugins>
<!-- 丢弃所有死信-->
<discardingDLQBrokerPlugindropAll="true" dropTemporaryTopics="true" dropTemporaryQueues="true" />
<!-- 丢弃指定死信-->
<!-- <discardingDLQBrokerPlugindropOnly="MY.EXAMPLE.TOPIC.29 MY.EXAMPLE.QUEUE.87" reportInterval="1000" />-->
<!--使用丢弃正则匹配到死信-->
<!--<discardingDLQBrokerPlugindropOnly="MY.EXAMPLE.TOPIC.[0-9]{3} MY.EXAMPLE.QUEUE.[0-9]{3}" reportInterval="3000"/>-->
</plugins>
...
</broker>
2)定时抛弃死信队列
默认情况下,ActiveMQ永远不会过期发送到DLQ的消息。但是,从ActiveMQ 5.12开始,deadLetterStrategy支持expiration属性,其值以毫秒为单位。