ActiveMQ 笔记(八)高级特性和大厂常考重点
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
1、可用性保证
引入消息队列之后该如何保证其高可用性?
持久化、事务、签收、 以及带复制的 Leavel DB + zookeeper 主从集群搭建
2、异步投递Async Sends
2.1 异步投递的定义
对于一个Slow Consumer,使用同步发送消息可能出现Producer堵塞的情况,慢消费者适合使用异步发送
如图介绍:

2.2 什么是异步投递
ActiveMQ支持同步,异步两种发送的模式将消息发送到broker,模式的选择对发送延时有巨大的影响。producer能达到怎么样的产出率(产出率=发送数据总量/时间)主要受发送延时的影响,使用异步发送可以显著提高发送的性能。
ActiveMQ默认使用异步发送的模式:除非明确指定使用同步发送的方式或者在未使用事务的前提下发送持久化的消息,这两种情况都是同步发送的。
如果你没有使用事务且发送的是持久化的消息,每一次发送都是同步发送的且会阻塞producer知道broker返回一个确认,表示消息已经被安全的持久化到磁盘。确认机制提供了消息安全的保障,但同时会阻塞客户端带来了很大的延时。
很多高性能的应用,允许在失败的情况下有少量的数据丢失。如果你的应用满足这个特点,你可以使用异步发送来提高生产率,即使发送的是持久化的消息。
异步发送
- 它可以最大化producer端的发送效率。我们通常在发送消息量比较密集的情况下使用异步发送,它可以很大的提升Producer性能;不过这也带来了额外的问题,
- 就是需要消耗更多的Client端内存同时也会导致broker端性能消耗增加;
- 此外它不能有效的确保消息的发送成功。在userAsyncSend=true的情况下客户端需要容忍消息丢失的可能。
2.3 官网配置参考(投递开启)
在高性能要求下,可以使用异步提高producer 的性能。但会消耗较多的client 端内存,也不能完全保证消息发送成功。在 useAsyncSend = true 情况下容忍消息丢失。
// 开启异步投递
activeMQConnectionFactory.setUseAsyncSend(true);

2.4 面试题: 异步消息如何确定发送成功?
异步发送丢失消息的场景是:生产者设置userAsyncSend=true,使用producer.send(msg)持续发送消息。
- 如果消息不阻塞,生产者会认为所有send的消息均被成功发送至MQ。
- 如果MQ突然宕机,此时生产者端内存中尚未被发送至MQ的消息都会丢失。
- 所以,正确的异步发送方法是需要接收回调的。
同步发送和异步发送的区别就在此,
- 同步大宋等send不阻塞了就表示一定发送成功了,
- 异步发送需要客户端回执并由客户端再判断一次是否发送成功
具体实现的代码案例:
JmsProduce_AsyncSend 在代码中接收回调的函数 :
package com.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.ActiveMQMessageProducer;
import org.apache.activemq.AsyncCallback;
import javax.jms.*;
import java.util.UUID;
public class Producer {
private static final String ACTIVEMQ_URL = "tcp://192.168.10.130:61616";
private static final String ACTIVEMQ_QUEUE_NAME = "Queue-异步投递回调";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL(ACTIVEMQ_URL);
//开启异步投递
activeMQConnectionFactory.setUseAsyncSend(true);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(ACTIVEMQ_QUEUE_NAME);
//向上转型到ActiveMQMessageProducer
ActiveMQMessageProducer activeMQMessageProducer = (ActiveMQMessageProducer) session.createProducer(queue);
for (int i = 0; i < 3; i++) {
TextMessage textMessage = session.createTextMessage("message-" + i);
textMessage.setJMSMessageID(UUID.randomUUID().toString() + "----orderAtguigu");
String textMessageId = textMessage.getJMSMessageID();
//使用ActiveMQMessageProducer的发送消息,可以创建回调
activeMQMessageProducer.send(textMessage, new AsyncCallback() {
@Override
public void onSuccess() {
System.out.println(textMessageId + "发送成功");
}
@Override
public void onException(JMSException exception) {
System.out.println(textMessageId + "发送失败");
}
});
}
activeMQMessageProducer.close();
session.close();
connection.close();
}
}

3、延时投递和定时投递
3.1 在配置文件中设置定时器开关 为 true
3.2 代码编写
- 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);
}
4、 Activemq的消息重试机制
(1)由消息丢失或延时而引发的问题——常见面试题
具体哪些情况会引发消息重发
- Client用了transactions且再session中调用了rollback
- Client用了transactions且再调用commit之前关闭或者没有commit
- Client再CLIENT_ACKNOWLEDGE的传递模式下,session中调用了recover
请说说消息重发时间间隔和重发次数
- 间隔:1
次数:6
每秒发6次
有毒消息Poison ACK
- 一个消息被redelivedred超过默认的最大重发次数(默认6次)时,消费的回个MQ发一个“poison ack”表示这个消息有毒,告诉broker不要再发了。这个时候broker会把这个消息放到DLQ(私信队列)。

重试机制的注意事项:
- 最多六次还没发出就会
- 加入DLQ (死信队列)
官网链接地址: http://activemq.apache.org/redelivery-policy
(2)简单案例说明:

(3)重发整合Spring 的配置

(4)重试机制的属性说明:

5、死信队列
(1)概念: Activemq中引入了“死信队列”(Dead Letter Queue) 的概念。即一条消息再被重发了多次后(默认为重发6次redeliveryCounter==6),将会被Activemq移入“死信队列”,开发人员可以在这个Queue中查看处理出错的消息,进行人工干预。

(2)死信队列的使用:处理失败的消息


(3)死信队列的配置介绍
- SharedDeadLetterStrategy

- IndividualDeadLetterStrategy


- 配置案例
a. 自动删除过期消息

b. 存放非持久消息到死队列中
在业务逻辑中,如果一个订单系统没有问题,则使用正常的业务队列,当出现问题,则加入死信队列 ,此时可以选择人工干预还是机器处理 。

6、 如何保证消息不被重复消费,幂等性的问题
如果消息是做数据库的插入操作,给这个消息一个唯一的主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据 。
如果不是,可以用redis 等的第三方服务,给消息一个全局 id ,只要消费过的消息,将 id ,message 以 K-V 形式写入 redis ,那消费者开始消费前,先去 redis 中查询有没消费的记录即可。

ActiveMQ 笔记(八)高级特性和大厂常考重点的更多相关文章
- Python:笔记(4)——高级特性
Python:笔记(4)——高级特性 切片 取一个list或tuple的部分元素是非常常见的操作.Python提供了切片操作符,来完成部分元素的选取 除了上例简单的下标范围取元素外,Python还支持 ...
- 分布式-信息方式-ActiveMQ的Destination高级特性1
ActiveMQ的Destination高级特性 Destination高级特性----->Composite Destinations 组合队列Composite Destinations : ...
- python3精简笔记(三)——高级特性
Python中 1行代码能实现的功能,决不写5行代码.请始终牢记,代码越少,开发效率越高. 切片 取一个list或tuple的部分元素是非常常见的操作.Python提供了切片(Slice)操作符 L ...
- ActiveMQ的Destination高级特性
1. Composite Destinations 组合目的地 组合队列Composite Destinations : 允许用一个虚拟的destination代表多个destinations ...
- python学习笔记(三)高级特性
一.切片 list.tuple常常截取某一段元素,截取某一段元素的操作很常用 ,所以python提供了切片功能. L=['a','b','c','d','e','f'] #取索引0,到索引3的元素,不 ...
- Python学习笔记4 高级特性_20170618
# 切片(获取list / tuple / 字符串 中指定的元素) l = list(range(10)) l[0:3] l[:3] # 0可以省略 l[:] # 全部 l[3:] # 最后的可以省略 ...
- 分布式-信息方式-ActiveMQ的Destination高级特性3
虚拟destination用来创建逻辑destination,客户端可以通过它来生产和消费消息,它会把消息映射到物理destination. ActiveMQ支持2种方式: 1:虚拟主题(Virtua ...
- 分布式-信息方式-ActiveMQ的Destination高级特性2
使用filtered destinations,在xml配置如下: <destinationInterceptors> <virtualDestinationInterceptor& ...
- html5学习笔记3——高级特性
一:Web存储 数据以 键/值 对存在, web网页的数据只允许该网页访问使用. web存储有两种: localStorage - 没有时间限制的数据存储,存于浏览器缓存 sessionStorage ...
随机推荐
- 教你配置windows上的windbg,linux上的lldb,打入clr内部这一篇就够了
一:背景 1. 讲故事 前几天公众号里有位兄弟看了几篇文章之后,也准备用windbg试试看,结果这一配就花了好几天,(づ╥﹏╥)づ,我想也有很多跃跃欲试的朋友在配置的时候肯定会遇到这样和那样的问题,所 ...
- 王颖奇 201771010129 第三周 Java基本程序设计总结
实验三 Java基本程序设计 实验时间 2018-9-13 201771010129 王颖奇 1.实验目的与要求 (1)进一步掌握Eclipse集成开发环境下java程序开发基本步骤: (2)熟悉PT ...
- 【Hadoop离线基础总结】Mac版VMware Fusion虚拟机磁盘挂载
步骤概览 1.打开所要挂载磁盘的虚拟机的设置(此时必须关机) 2.打开硬盘设置 3.添加设备 4.选择新硬盘 5.设置如下图 6.将虚拟机开机,输入 df-lh ,查看当前虚拟机磁盘 7.输入 fdi ...
- 【FreeRTOS学习05】深度解剖FreeRTOSConfig.h实现对系统的自定义剪裁
ROM/RAM太小,因此要对系统进行剪裁: 相关文章 [FreeRTOS实战汇总]小白博主的RTOS学习实战快速进阶之路(持续更新) 文章目录 相关文章 1 系统的剪裁 2 FreeRTOSConfi ...
- ocelot jwt 进行统一验证
前一个帖子发了有关jwt 验证api的内容,这一次将jwt集成到ocelot网关中. ocelot集成jwt有一个很不错的nuget包,ocelot.jwtauthorize ,但是这个包似乎支持n ...
- 测试开发专题:如何在spring-boot中进行参数校验
上文我们讨论了spring-boot如何去获取前端传递过来的参数,那传递过来总不能直接使用,需要对这些参数进行校验,符合程序的要求才会进行下一步的处理,所以本篇文章我们主要讨论spring-boot中 ...
- dedecms_v5.7的apache文件名解析漏洞的学习
0x00 Apache文件名解析漏洞 Apache是一个Web服务器,可以提供web服务.配合java中间件.PHP实现动态页面访问. Apache和PHP通过接口接入后,Apache接受用户的请求, ...
- ql的python学习之路-day1
写在前面的话:万事开头难,算是系统学习python的一个月了吧,总该写点什么来记录一下,之前看老男孩day1的视频没有开通博客,这次给补上,对于学python还是要好好努力,不能半途而废,还是那句老话 ...
- Java Web之路一:过滤器(Filter)
一.过滤器(Filter)简介 过滤器是对web资源进行拦截,做一些处理后再交给下一个过滤器或Servlet处理,主要可以拦截request和response 过滤器是以一种组件的形式与web程序绑定 ...
- poj3648 2-SAT进阶 记录点拓扑
Wedding Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10556 Accepted: 3220 Specia ...