这次真的忽略了一些ActiveMQ内心的娇艳
好久没总结了,内心有点空虚了,所以今天主要给园里的朋友们分享一点儿这几天使用ActiveMQ过程中踩过的小坑,虽然说这东西简单易用,代码几行配置也就几行,问题不大但是后果有点严重,所以就要必要总结一下了。
首先ActiveMQ有俩种消息队列模式:点对点和发布订阅,这俩种都有不可替代的应用场景,前者适用于消息唯一传递的业务,后者适用于分布式环境下进行多面数据同步的操作。
其次一些关于它的官方简介和安装步骤我就不占博客园数据库的内存了,写了也没啥鸟用,用烂的朋友想要提取点儿精华,没接触过的朋友请先安装一个玩玩点对点和发布订阅模式吧(http://www.cnblogs.com/1315925303zxz/p/6377551.html),理解一下这俩种机制的区别和出现消息临界值时的特性,我下面也放一些我前期用于测试的Demo,其中总结了一些他们二者的主要区别,都是实战中必须要考虑的因素可以参考:
假设:存在一个消息生产者、多个消费者,分别在点对点和发布订阅模式下进行消息获取,当出现消息临界值的时候都有什么现象?这些需要朋友你自己体会,我能做的只有送上代码供各位测试了。
消息生产者
public class ProducerDemo2 {
private static Random r = new Random();
public static void main(String[] args) {
ConnectionFactory connectionFactory; // 连接工厂
Connection connection = null; // 连接
Session session; // 会话 接受或者发送消息的线程
Destination destination; // 消息的目的地
MessageProducer messageProducer;//消息生产者
// 实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://10.0.40.73:61616"); //用户名、密码、连接地址
try {
// 通过连接工厂获取连接
connection = connectionFactory.createConnection();
// 启动连接
connection.start();
// 创建session
session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); //true:支持事务 false:不支持事务
// 创建/选择一个消息队列
destination = session.createQueue("BMW"); //点对点
//destination = session.createTopic("ToyotaYQ"); //发布订阅
//创建消息生产者
messageProducer = session.createProducer(destination);
//创建一条文本消息
int num = r.nextInt(100);
TextMessage message = session.createTextMessage("ActiveMQ 生产者2发送消息"+num);
System.out.println("生产者2发送消息:"+num);
//通过消息生产者发出消息
messageProducer.send(message);
//提交
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
消息消费者(可以copy多个进行消息争抢测试)
public class ConsumerDemo2 {
// private static final String USERNAME =
// ActiveMQConnection.DEFAULT_USER;//默认连接用户名(amdin)
// private static final String PASSWORD =
// ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码(admin)
// private static final String BROKEURL =
// ActiveMQConnection.DEFAULT_BROKER_URL;//默认连接地址(tcp://localhost:61616)
public static void main(String[] args) {
ConnectionFactory connectionFactory; // 连接工厂
Connection connection = null; // 连接
Session session; // 会话 接受或者发送消息的线程
Destination destination; // 消息的目的地
MessageConsumer messageConsumer; // 消息的消费者
// 实例化连接工厂
connectionFactory = new ActiveMQConnectionFactory("admin", "admin", "tcp://10.0.40.73:61616"); //用户名、密码、连接地址
try {
// 通过连接工厂获取连接
connection = connectionFactory.createConnection();
// 启动连接
connection.start();
// 创建session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 创建/选择一个消息队列
destination = session.createQueue("BMW"); //点对点模式
//destination = session.createTopic("ToyotaYQ"); //发布订阅模式
// 创建消息消费者
messageConsumer = session.createConsumer(destination);
while (true) {
//设置消费者接收消息的时间(3s)
TextMessage textMessage = (TextMessage)messageConsumer.receive(3000);
if(textMessage == null){
System.out.println("没有消息");
}else{
System.out.println(textMessage.getText());
//System.exit(0);
}
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
注意事项:
1、生产者发送消息时必须支持事务,就是创建消息会话的时候设置为true,否则会出现“javax.jms.IllegalStateException: Not a transacted session”异常。消费者可以不支持。
2、点对点模式下,同一时刻只能有一个消费者从队列中获取消息内容,如果存在多个消费者,则会出现消息争抢现象直到消息全部抢完,处于阻塞状态,如果再有消息被放进来时,接着会进行争抢,但是只会有一个消费者获取到消息,不会出现多个消费者抢到消息的情况。
3、点对点模式下,生产者发送消息时,消费者可以处于离线状态,当消费者再次运行时可以接收到历史消息;但是在发布订阅模式下,消费者必须处于运行状态获取消息,历史消息也是不会被获取到的。
实战上线后踩过的坑以及解决方案:
1、用户订单入库成功后发送到MQ中的订单消息丢失,出现处理订单遗漏的情况?
解决方案1:打开消息持久开关。
因为Activemq支持两种消息传送模式:
PERSISTENT (持久消息)该模式是activemq默认的传送方式,此模式下可以保证消息只会被成功传送一次和成功使用一次,消息具有可靠性。在消息传递到目标消费者,在消费者没有成功应答前,消息不会丢失。所以很自然的,需要一个地方来持久性存储。如果消息消费者在进行消费过程发生失败,则消息会被再次投递;
NON_PERSISTENT(非持久消息)该模式适用于消息不重要的,可以接受消息丢失的哪一类消息,这种消息只会被投递一次,消息不会在持久性存储中存储,也不会保证消息丢失后的重新投递。
与spring整合使用ActiveMQ配置文件如下:
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory"/>
<!-- deliveryMode, priority, timeToLive 的开关,要生效,必须配置为true,默认false-->
<property name="explicitQosEnabled" value="true" />
<!-- 【发送模式 DeliveryMode.NON_PERSISTENT=1:非持久 ; DeliveryMode.PERSISTENT=2:持久】-->
<property name="deliveryMode" value="2" />
</bean>
解决方案2:设置消息重发机制。
ActiveMQ针对消息丢失情况提供了消息重发机制,假设消息发送失败,为了解决这一尴尬局面,我们可以在实际项目中配置消息重发机制,以防万一。
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.136.139:61616"/>
<property name="redeliveryPolicy" ref="activeMQRedeliveryPolicy" /> <!-- 引用重发机制 -->
</bean> <!-- ActiveMQ消息发送失败后的重发机制 -->
<bean id="activeMQRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<!--是否在每次尝试重新发送失败后,增长这个等待时间 -->
<property name="useExponentialBackOff" value="true"></property>
<!--重发次数,默认为6次 这里设置为1次 -->
<property name="maximumRedeliveries" value="1"></property>
<!--重发时间间隔,默认为1秒 -->
<property name="initialRedeliveryDelay" value="1000"></property>
<!--第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value -->
<property name="backOffMultiplier" value="2"></property>
<!--最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第
二次重连时间间隔为 20ms,第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。 -->
<property name="maximumRedeliveryDelay" value="1000"></property>
</bean>
前天任务调度服务上线后,出现消息丢失的情况,根据以上解决方案是否能够根治这种情况,本人也是不太能够保证,希望稍后能在留言区得到各位老兄的帮助。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan
这次真的忽略了一些ActiveMQ内心的娇艳的更多相关文章
- python爬虫10 | 网站维护人员:真的求求你们了,不要再来爬取了!!
今天 小帅b想给大家讲一个小明的小故事 ... 话说 在很久很久以前 小明不小心发现了一个叫做 学习python的正确姿势 的公众号 从此一发不可收拾 看到什么网站都想爬取 有一天 小明发现了一个小黄 ...
- Red Hat 4.4.7-4上安装glances填大大大坑实录,我的内心是崩溃的!!!
今天的任务是在公司的一台压力测试机上安装一个性能监控工具:glances 因为以前我已经多次安装和使用这个工具,我大意的以为整个过程是这样的: 分分钟搞定完事 然而 我们公司的服务器版本实在是太老了, ...
- Spring事务失效的 8 大原因,这次可以吊打面试官了!
今天再来一篇<吊打面试官>系列,这次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新--) 前几天栈长不是发了一篇文章,里面有一个关于事务失效的问题: 用 Spring ...
- 一个粗心的Bug,JSON格式不规范导致AJAX错误
一.事件回放 今天工作时碰到了一个奇怪的问题,这个问题很早很早以前也碰到过,不过没想到过这么久了竟然又栽在这里. 当时正在联调一个项目,由于后端没有提供数据接口,于是我直接本地建立了一个 json ...
- FZU 1018 枚举dp
题意 给出一个数字组成的立方体 在其中选取一个体 使这个体中的数字之和最小 不可以不选 fzu的题目分类动态规划里面不是按难度排得 是按照题号..记得以前做题碰到过算 矩阵里面求子矩阵的最大和的 不会 ...
- 关于css3的自定义字体
css3的@font-face属性打破了中文页面字体一成不变的格局,但今天本菜在用的时候并不那么爽.开始各种引用外部ttf文件失败.下了300M+的字体文件,苦逼的试了一下午.终于有一个ttf引用成功 ...
- 关于Try/Catch 代码块
应当放在Try/Catch 代码块中的常见任务包括连接到一个数据库或与其交互.处理文件.调用Web 服务. 老实说,我这人很少有打破沙锅问到底的精神.不过昨晚听一技术人员跟他的项目经理说要在程序中使用 ...
- Ubuntu 12.04 Openstack Essex 安装(单节点)
这是陈沙克一篇非常好的博文,当时在进行openstack排错的时候,多亏了这篇文章里面有些内容 帮我找到了问题的所在: 原文:http://www.chenshake.com/ubuntu-12-04 ...
- Bittersweet——NOIP2018 游记
p { font-size: 16px; line-height: 1.5em; } blockquote { font-family: 'Times New Roman', 楷体; text-ali ...
随机推荐
- DevOps之唠叨话
唠叨话 教学:人类培养态度.传授知识.训练技能的活动. 教学手册(Teaching Manual) 教学形式:教材与课程,师生(一对一.一对多).教学内容:系统框架和问答机制,结构(前言.目录.正文. ...
- Html 初识样式表&选择器
样式表&类选择器分类 样式表分类: 1.内联式样式表:在标签内部写样式代码,精确但不方便,增加工作量,后期修改麻烦. 2.嵌入式样式表:一般写在head内 以<style>.... ...
- 中秋H5,这篇脑洞开的可以!
案例:嫦娥--寻开心出品:凯迪仕 1.内容:这是一支视频类H5案例.Loading完毕进入页面,首屏提示案例最佳观看方式为先锁屏再横屏.点击开始按钮播放视频,视频讲述"葫芦娃"缠着 ...
- 搭建阿里云 centos mysql tomcat jdk
[toc] 阿里云使用centos 登录 http://www.aliyun.com/ 点击登录 进入控制 https://home.console.aliyun.com/ 云服务器 运行中 把ip输 ...
- 基于HTML5及WebGL开发的2D3D第一人称漫游进行碰撞检测
为了实现一个基于HTML5的场景小游戏,我采用了HT for Web来实现,短短200行代码,我就能实现用“第一人称”来操作前进后退上下左右,并且实现了碰撞检测. 先来看下实现的效果:http://h ...
- Python学习笔记(二)-Python文件类型及编程模式
Python环境搭建:linux,Windows... Linux下:[root@localhost StudyPython]# python #进入交互模式Python 2.7.11 (defaul ...
- LeetCode 605. Can Place Flowers (可以种花)
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...
- 关于 Swift 4 中内存安全访问
前言 本文主要翻译今年 The Swift Programming Language (Swift 4) 中新出的章节 -<Memory Safety>.在 Swift 4 中,内存安全访 ...
- x86-64栈帧中的“红色区域” red zone of stack frame on x86-64
前几天看System V AMD64 ABI标准的时候发现栈帧的顶部后面有一块"red zone",在学cs:app3e/深入理解操作系统的时候并没有遇到这个,总结一下. 引用标准 ...
- HDU 6069 Counting Divisors
Counting Divisors Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Oth ...