一. 修改访问账号、密码
在activemq.xml文件中修改如下:
<plugins>
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="root" password="123" groups="users,admins"/>
</users>
</simpleAuthenticationPlugin>
</plugins>
修改username和password,group表示角色名,我这里设置了自带的角色users和admins。
二. 故障转移
failover:(tcp://localhost:61616,tcp://localhost:61617,tcp://localhost:61618)?randomize=false&timeout=5000
我这里设置了randomize为false,表示当主服务器不可用时,从右边的从服务器列表选举一个作为新的主服务器。
详细配置,可参考官网: http://activemq.apache.org/failover-transport-reference.html
三. 事务
- Session.SESSION_TRANSACTED:事务,使用session.commit();提交
- Session.AUTO_ACKNOWLEDGE:在消费者receive或者MessageListener成功返回后,自动提交
- Session.CLIENT_ACKNOWLEDGE:使用message.acknowledge()手动提交,只要被消费的消息,都会被一次性提交。
- Session.OPS_OK_ACKNOWLEDGE:批量提交,允许有重复的消息,重复的消息的消息头中的JMSRedelivered被设置为true
关于第一种的Session在生产者中的使用:
connection.createSession(true, Session.SESSION_TRANSACTED); 第一个参数设置为true,表示使用事务
for (int i = 0; i < 10000; i++) {
String messageBody = "This is NO." + i + " message";
TextMessage textMessage = session.createTextMessage(messageBody);
publisher.send(textMessage);
if (i == 5000)
session.commit();
}
然后访问 localhost:8161,查看入队的消息数,结果为5001。说明提交了从0到5000的消息。
再来看下session.rollback()的用法。
try {
.....................
for (int i = 0; i < 10000; i++) {
String messageBody = "This is NO." + i + " message"; System.out.println(1 / 0);
TextMessage textMessage = session.createTextMessage(messageBody);
publisher.send(textMessage);
if (i == 5000)
session.commit();
}
} catch (Exception e) {
try {
Objects.requireNonNull(session).rollback();
} catch (JMSException e) {
e.printStackTrace();
}
}
结果一个信息都没有发送成功。入队失败。
再来看在消费者中的使用:
session = connection.createSession(true, TopicSession.SESSION_TRANSACTED);
destination = session.createTopic(destinationName);
subscriber = session.createSubscriber(destination);
while (true) {
Message message = subscriber.receive();
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println(textMessage.getText());
}
}
事务不提交试下,能输出信息,消息能出队。说明这个Session用法对于消费者没用。
再看下回滚对于消费者的影响:
while (true) {
Message message = subscriber.receive();
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println(textMessage);
System.out.println(1 / 0);
session.commit();
}
}
} catch (Exception e) {
try {
Objects.requireNonNull(session).rollback();
} catch (JMSException e) {
e.printStackTrace();
}
}
结果是消费者无法继续获得消息,也无法出队。
总结:Session.SESSION_TRANSACTED 对于生产者而言,session.commit()控制了消息的入队,session.rollback()会导致消息无法入队。 对于消费者而言,session.commit()不影响消费者获得消息,也不影响消息的出队,但是session.rollback()会导致后续的消息无法出队,同时中断消费者获得消息。
Session.AUTO_ACKNOWLEDGE 对于生产者而言,发送消息中如果遇到异常,会中断消息的入队。比如第50条发生异常,并不影响前49条的入队。
对于消费者而言。自动获取消息,消息正常出队。但是遇到异常,消费者中断获取消息,并且后续的消息无法出队。
Session.CLIENT_ACKNOWLEDGE 生产者情况同上。即使不加acknowledge,也会入队。发送消息中如果遇到异常,会中断消息的入队。消费者acknowledge影响消息的出队。但不影响获得消息。但是遇到异常,消费者中断获取消息,并且后续的消息无法出队。
四. 优化确认
用于单个批次操作中确认一系列消息。
<property name="optimizeAcknowledge" value="true"/>
<property name="optimizeAcknowledgeTimeOut" value="300"/>
optimizeAcknowlede:默认是false,可设置为true,提高吞吐量
optimizeAcknowledgeTimeOut :确认的超时时间,默认是300ms,0表示禁用