一、引入消息队列后,如何保证其高可用性
持久化、事务、签收、 以及带复制的 Leavel DB + zookeeper 主从集群搭建
二、异步投递(Async send)
对于一个慢消费者,使用同步有可能造成堵塞,消息消费较慢时适合用异步发送消息
activemq 支持同步异步 发送的消息,默认异步。当你主动设定同步发送的方式和 未使用事务的情况下发持久化消息,这时是同步的。
如果没有使用事务,且发送的是持久化消息,每次发送都会阻塞一个生产者直到 broker 发回一个确认,这样做保证了消息的安全送达,但是会阻塞客户端,造成很大延时 。
在高性能要求下,可以使用异步提高producer 的性能。但会消耗较多的client 端内存,也不能完全保证消息发送成功。在useAsyncSend = true 情况下容忍消息丢失。
根据官网描述,设置消息异步有三种方式:
url 后面加参数
开启ActivemqFactury 的Async 为true
将connection 设Async 为true
但这样设置为异步发送会有一个问题:允许消息丢失,那如何做到消息投递快并且消息不会被丢失呢?
异步发送消息丢失的情况场景是: UseAsyncSend 为 true 使用 producer(send)持续发送消息,消息不会阻塞,生产者会认为所有的 send 消息均会被发送到 MQ ,如果MQ 突然宕机,此时生产者端尚未同步到 MQ 的消息均会丢失 。
故 正确的异步发送方法需要接收回调
同步发送和异步发送的区别就在于 :
同步发送send 不阻塞就代表消息发送成功
异步发送需要接收回执并又客户端在判断一次是否发送
在代码中接收回调的方法 :
activeMQConnectionFactory.setUseAsyncSend(true);
……
for (int i = 1; i < 4 ; i++) {
textMessage = session.createTextMessage("msg--" + i);
//设置一个唯一id标识此消息
textMessage.setJMSMessageID(UUID.randomUUID().toString()+"-- orderr");
String msgid = textMessage.getJMSMessageID();
messageProducer.send(textMessage, new AsyncCallback() {
@Override
public void onSuccess() {
// 发送成功怎么样
System.out.println(msgid+"has been successful send ");
}
@Override
public void onException(JMSException e) {
// 发送失败怎么样
System.out.println(msgid+" has been failure send ");
}
});
}
三、延迟投递和定时投递
① 在配置文件中设置定时器开关 为 true
②代码编写
Java 代码中封装的辅助消息类型 ScheduleMessage
可以设置的 常用参数 如下:
long delay = 3 * 1000 ;
long perid = 4 * 1000 ;
int repeat = 7 ;
for (int i = 1; i < 4 ; i++) {
TextMessage textMessage = session.createTextMessage("delay msg--" + i);
// 消息每过 3 秒投递,每 4 秒重复投递一次 ,一共重复投递 7 次
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,delay);
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD,perid);
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT,repeat);
messageProducer.send(textMessage);
}
四、消息重试机制
最多六次还没发出就会
加入DLQ (死信队列)
五、死信队列
可以修改消息进入死信队列的重发次数条件为3次 // 三次的意思是不计算本来发送的第一次
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
在spring 中使用 死信机制
在业务逻辑中,如果一个订单系统没有问题,则使用正常的业务队列,当出现问题,则加入死信队列 ,此时可以选择人工干预还是机器处理 。
死信队列默认是全部共享的,但是也可以设置独立的死信队列
独立的死信队列配置
六、如何保证消息不会被重复消费,也就是幂等性问题。
七、ActiveMQ中的观察者模式
观察者模式 、 发布订阅者设计模式 :
观察者模式 : 对象间的一对多的依赖关系
何谓观察者模式?观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。
在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。
发布订阅者 : 是观察者模式的一个概念的变种,
发布/订阅者模式与观察者模式主要有以下几个不同点:
- 在观察者模式中,主体维护观察者列表,因此主体知道当状态发生变化时如何通知观察者。然而,在发布者/订阅者中,发布者和订阅者不需要相互了解。它们只需在中间层消息代理(或消息队列)的帮助下进行通信。
- 在发布者/订阅者模式中,组件与观察者模式完全分离。在观察者模式中,主题和观察者松散耦合。
- 观察者模式主要是以同步方式实现的,即当发生某些事件时,主题调用其所有观察者的适当方法。发布服务器/订阅服务器模式主要以异步方式实现(使用消息队列)。
- 发布者/订阅者模式更像是一种跨应用程序 模式。发布服务器和订阅服务器可以驻留在两个不同的应用程序中。它们中的每一个都通过消息代理或消息队列进行通信。