好久没总结了,内心有点空虚了,所以今天主要给园里的朋友们分享一点儿这几天使用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内心的娇艳的更多相关文章

  1. python爬虫10 | 网站维护人员:真的求求你们了,不要再来爬取了!!

    今天 小帅b想给大家讲一个小明的小故事 ... 话说 在很久很久以前 小明不小心发现了一个叫做 学习python的正确姿势 的公众号 从此一发不可收拾 看到什么网站都想爬取 有一天 小明发现了一个小黄 ...

  2. Red Hat 4.4.7-4上安装glances填大大大坑实录,我的内心是崩溃的!!!

    今天的任务是在公司的一台压力测试机上安装一个性能监控工具:glances 因为以前我已经多次安装和使用这个工具,我大意的以为整个过程是这样的: 分分钟搞定完事 然而 我们公司的服务器版本实在是太老了, ...

  3. Spring事务失效的 8 大原因,这次可以吊打面试官了!

    今天再来一篇<吊打面试官>系列,这次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新--) 前几天栈长不是发了一篇文章,里面有一个关于事务失效的问题: 用 Spring ...

  4. 一个粗心的Bug,JSON格式不规范导致AJAX错误

    一.事件回放  今天工作时碰到了一个奇怪的问题,这个问题很早很早以前也碰到过,不过没想到过这么久了竟然又栽在这里. 当时正在联调一个项目,由于后端没有提供数据接口,于是我直接本地建立了一个 json ...

  5. FZU 1018 枚举dp

    题意 给出一个数字组成的立方体 在其中选取一个体 使这个体中的数字之和最小 不可以不选 fzu的题目分类动态规划里面不是按难度排得 是按照题号..记得以前做题碰到过算 矩阵里面求子矩阵的最大和的 不会 ...

  6. 关于css3的自定义字体

    css3的@font-face属性打破了中文页面字体一成不变的格局,但今天本菜在用的时候并不那么爽.开始各种引用外部ttf文件失败.下了300M+的字体文件,苦逼的试了一下午.终于有一个ttf引用成功 ...

  7. 关于Try/Catch 代码块

    应当放在Try/Catch 代码块中的常见任务包括连接到一个数据库或与其交互.处理文件.调用Web 服务. 老实说,我这人很少有打破沙锅问到底的精神.不过昨晚听一技术人员跟他的项目经理说要在程序中使用 ...

  8. Ubuntu 12.04 Openstack Essex 安装(单节点)

    这是陈沙克一篇非常好的博文,当时在进行openstack排错的时候,多亏了这篇文章里面有些内容 帮我找到了问题的所在: 原文:http://www.chenshake.com/ubuntu-12-04 ...

  9. Bittersweet——NOIP2018 游记

    p { font-size: 16px; line-height: 1.5em; } blockquote { font-family: 'Times New Roman', 楷体; text-ali ...

随机推荐

  1. [解读REST] 5.Web的需求 & 推导REST

    衔接上文[解读REST] 4.基于网络应用的架构风格,上文总结了一些适用于基于网络应用的架构风格,以及其评估结果.在前文的基础上,本文介绍一下Web架构的需求,以及在对Web的关键协议进行设计和改进的 ...

  2. Python数据分析(二): Pandas技巧 (1)

    第一部分: ipython http://www.cnblogs.com/cgzl/p/7623347.html 第二部分: numpy http://www.cnblogs.com/cgzl/p/7 ...

  3. 【学习】原生js学习笔记1:添加class和使input为不可用

    <input type="checkbox" id="new_check" onChange="noUse()" checked> ...

  4. 深入浅出 SpringMVC - 2 提升篇

    前言: 本篇笔记是继 深入浅出 SpringMVC - 1 后的续篇,主要介绍了 SpringMVC 的实际小应用,包括 SpringMVC 的数据格式化.使用 JSR 303 验证标准 在 Spri ...

  5. 数据挖掘 ID3

    本文讲的是数据挖掘中的ID3,这个有很多人做了,我也没有说什么改善,只是要考试,用我考试记录的来写,具有很大主观性,如果看到有觉得不对或感觉不好,请关掉浏览器或和我说,请不要生气或发不良的言论. 决策 ...

  6. Unix时代的开创者Ken Thompson

    自图灵奖诞生以来,其获得者一直都是计算机领域的科学家与学者,而在所有这些界的图灵奖中只有唯一的一届有个例外,那就是Ken Thompson与Dennis M. Ritchie,他们都是计算机软件工程师 ...

  7. QQ顶部的消息,联系人切换

    高仿ios SegmentView 以前做过的一个项目美工设计的页面包含这个控件,和QQ消息页面顶部的效果一样,其实,这个控件是ios7的分段控制,android没有这个控件,不过实现起来也比较简单, ...

  8. java压缩包上传,解压,预览(利用editor.md和Jstree实现)和下载

    java压缩包上传,解压,预览(利用editor.md和Jstree实现)和下载 实现功能:zip文件上传,后台自动解压,Jstree树目录(遍历文件),editor.md预览 采用Spring+Sp ...

  9. LeetCode 1. Two Sum (两数之和)

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  10. 读书笔记-你不知道的JS上-this

    关于this 与静态词法作用域不用,this的指向动态绑定,在函数执行期间才能确定.感觉有点像C++的多态? var a = 1; var obj = { a: 2, fn: function() { ...