持久性
非持久:当服务器宕机,消息不存在
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
持久化:当服务器宕机,消息依然存在
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
事务
生产者事务
当我们在创建一个session的时候,我们可以指定是否开启事务,代码如下:
false:表示不开启事务,只要执行send方法,表示消息就进入到队列中
true:表示开启事务,
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
当把事务 设为 true的时候 ,当我们发送消息的时候,需要手动提交,代码 session.commit()
事务的作用:
当我们批处理一次发送多个个消息,如果中间一条消息出现了异常,我们可以利用事务控制,该批消息要么全部发送成功,要么可以回滚,
示例代码:
public class ActivemqProducer {
static String BROCKER_URL = "tcp://192.168.72.129:61616";
static String QUEUE_NAME = "queue_name01";
public static void main(String[] args) throws JMSException {
// 1. 创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(BROCKER_URL);
// 2. 获取连接 并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 3. 创建session 并开启事务,参数一:事务,参数二:签收
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//4. 创建目的地,队列
Queue queue = session.createQueue(QUEUE_NAME);
// 5.创建消息生产者
MessageProducer messageProducer = session.createProducer(queue);
try {
// 6.通过 messageProducer 发送3条消息
for (int i = 1; i <= 3; i++) {
TextMessage textMessage = session.createTextMessage("消息 ->" + i);
messageProducer.send(textMessage);
}
// 提交事务
session.commit();
} catch (JMSException e) {
// 回滚
session.rollback();
e.printStackTrace();
}
System.out.println("发送消息完成......");
// 7.关闭资源
messageProducer.close();
session.close();
connection.close();
}
}
消费者事务
当消费者开启事务,如果我们消费了消息,不提交事务,那么消息将一直不出队列,该消息可以一直被消费,可以被重复消费
当我们在消费消息的时候,如果其中一个消息出现异常,我们可以重新消费
签收(Acknowledge)
在创建session的时候我们可以指定 签收模式,签收模式有以下几种:
- 自动签收 Session.AUTO_ACKNOWLEDGE
- 手动签收 Session.CLIENT_ACKNOWLEDGE
- 允许重复消息 Session.DUPS_OK_ACKNOWLEDGE
- 以事务方式 Session.SESSION_TRANSACTED
签收注意侧重 消费者
自动签收
该模式下当我们消费者消费了消息,那么该 消息就自动签收了,消息出队列。
CLIENT_ACKNOWLEDGE(手动签收)
该模式下,消费者以非事务的方式消费消息。
- 如果不手动签收,那么该消息就不会出队列,
- 需要对消费的每一条消息确认签收: message.acknowledge();
- 这样消息确认消费了,我们手动签收,消息出队列,可以保证消息的可靠性
如果开启了事务的同时也开启了CLIENT_ACKNOWLEDGE,那么以事务的commit为准,什么时候commit,消息什么时候出队列,与确认签收无关了
public class ActivemqConsumer {
static String BROKER_URL = "tcp://192.168.72.129:61616";
static String QUEUE_NAME = "queue_name04";
public static void main(String[] args) throws JMSException {
// 1.创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
// 2.创建连接并启动
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 3.创建session
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
// 4.创建目的地
Queue queue = session.createQueue(QUEUE_NAME);
// 5.创建消费者
MessageConsumer consumer = session.createConsumer(queue);
// 6.从目的地取消息
while (true) {
// 如果没有消息,g该方法会阻塞
TextMessage message = (TextMessage) consumer.receive();
if (message != null) {
System.out.println("消费者收到消息:" + message.getText());
// 手动签收
message.acknowledge();
} else
break;
}
// 7.关闭资源
consumer.close();
session.close();
connection.close();
}
}
签收和事务的关系
在事务的会话中,当一个事务被成功提交则消息被自动签收。
如果事务回滚,则消息会被再次传送。(以事务为大)
非事务的回话中,消息何时被确认签收取决于创建session时设置的签收模式
JMS点对点,发布订阅总结
点对点:
发布订阅: