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 ...
随机推荐
- 你离高薪 offer 只差一个Redis入门,我是认真的
说起来,可能有些小伙伴会不相信,我是第一次用 Redis,真的.因为公司小,业务量小,Redis 根本派不上用场.不过,最近打算把系统升级一下,顺带把当下时髦的技术入个门,"与时俱进&quo ...
- Spring MVC教程——检视阅读
Spring MVC教程--检视阅读 参考 Spring MVC教程--一点--蓝本 Spring MVC教程--c语言中午网--3.0版本太老了 Spring MVC教程--易百--4.0版本不是通 ...
- 集群、分布式、SOA、微服务、webService等思想的整理
引子:前几天甲方问我,他用wpf弄个界面,能不能通过其他语言给他传输数据,我由此想到了webservice(此时此刻,我也没有用过webServices),作日翻阅了一些资料,对这块技术有了个大概的了 ...
- 【图论算法】LCA最近公共祖先问题
LCA模板题https://www.luogu.com.cn/problem/P3379题意理解 对于有根树T的两个结点u.v,最近公共祖先LCA(u,v)表示一个结点x,满足x是u.v的祖先且x的深 ...
- ASP.NET Core依赖注入(DI)
ASP.NET Core允许我们指定注册服务的生存期.服务实例将根据指定的生存时间自动处理.因此,我们无需担心清理此依赖关系,他将由ASP.NET Core框架处理.有如下三种类型的生命周期. 关于依 ...
- Kappa(cappa)系数只需要看这一篇就够了,算法到python实现
1 定义 百度百科的定义: 它是通过把所有地表真实分类中的像元总数(N)乘以混淆矩阵对角线(Xkk)的和,再减去某一类地表真实像元总数与被误分成该类像元总数之积对所有类别求和的结果,再除以总像元数的平 ...
- Iterator模式C++实现
原文链接 #include <iostream> using namespace std; typedef int DATA; class Iterator; // 容器的抽象基类 cla ...
- Mysql之Linux中mariadb主从复制
master主机mysql安装配置 1.下载mariadb(Centos7开始mysql的名字) (1)其它方式(不推荐):rpm安装/软件源安装 (2)yum安装(推荐): ①centos官方的yu ...
- 汉字统计(hdu2030)
输入格式:一个整型,再循环带有空格的字符串 思考:用scanf_s()函数输入整型,然后一个大循环,再用gets_s()函数输入带空格的字符串. 注意:scanf_s()函数多加了%c,&d, ...
- 【数据分析入门】之Spyder中如何让图表单独显示出来
一般图表只显示在ipython console中,且是静态,无法进行放大,移动等操作解决方案:[win]tools——preferences——ipython console——graphics中ba ...