消息队列 折腾ActiveMQ时遇到的问题和解决方法
1.先讲严重的:服务挂掉。
这得从ActiveMQ的储存机制说起。在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的,它们的最大限制在配置文件的<systemUsage>节点中配置。但是,在非持久化消息堆积到一定程度,内存告急的时候,ActiveMQ会将内存中的非持久化消息写入临时文件中,以腾出内存。虽然都保存到了文件里,但它和持久化消息的区别是,重启后持久化消息会从文件中恢复,非持久化的临时文件会直接删除。
那如果文件增大到达了配置中的最大限制的时候会发生什么?我做了以下实验:
设置2G左右的持久化文件限制,大量生产持久化消息直到文件达到最大限制,此时生产者阻塞,但消费者可正常连接并消费消息,等消息消费掉一部分,文件删除又腾出空间之后,生产者又可继续发送消息,服务自动恢复正常。
设置2G左右的临时文件限制,大量生产非持久化消息并写入临时文件,在达到最大限制时,生产者阻塞,消费者可正常连接但不能消费消息,或者原本慢速消费的消费者,消费突然停止。整个系统可连接,但是无法提供服务,就这样挂了。
具体原因不详,解决方案:尽量不要用非持久化消息,非要用的话,将临时文件限制尽可能的调大。
2.丢消息。
这得从java的java.net.SocketException异常说起。简单点说就是当网络发送方发送一堆数据,然后调用close关闭连接之后。这些发送的数据都在接收者的缓存里,接收者如果调用read方法仍旧能从缓存中读取这些数据,尽管对方已经关闭了连接。但是当接收者尝试发送数据时,由于此时连接已关闭,所以会发生异常,这个很好理解。不过需要注意的是,当发生SocketException后,原本缓存区中数据也作废了,此时接收者再次调用read方法去读取缓存中的数据,就会报Software caused connection abort: recv failed错误。
通过抓包得知,ActiveMQ会每隔10秒发送一个心跳包,这个心跳包是服务器发送给客户端的,用来判断客户端死没死。如果你看过上面第一条,就会知道非持久化消息堆积到一定程度会写到文件里,这个写的过程会阻塞所有动作,而且会持续20到30秒,并且随着内存的增大而增大。当客户端发完消息调用connection.close()时,会期待服务器对于关闭连接的回答,如果超过15秒没回答就直接调用socket层的close关闭tcp连接了。这时客户端发出的消息其实还在服务器的缓存里等待处理,不过由于服务器心跳包的设置,导致发生了java.net.SocketException异常,把缓存里的数据作废了,没处理的消息全部丢失。
解决方案:用持久化消息,或者非持久化消息及时处理不要堆积,或者启动事务,启动事务后,commit()方法会负责任的等待服务器的返回,也就不会关闭连接导致消息丢失了。
3.持久化消息非常慢。
默认的情况下,非持久化的消息是异步发送的,持久化的消息是同步发送的,遇到慢一点的硬盘,发送消息的速度是无法忍受的。但是在开启事务的情况下,消息都是异步发送的,效率会有2个数量级的提升。所以在发送持久化消息时,请务必开启事务模式。其实发送非持久化消息时也建议开启事务,因为根本不会影响性能。
4.消息的不均匀消费。
有时在发送一些消息之后,开启2个消费者去处理消息。会发现一个消费者处理了所有的消息,另一个消费者根本没收到消息。原因在于ActiveMQ的prefetch机制。当消费者去获取消息时,不会一条一条去获取,而是一次性获取一批,默认是1000条。这些预获取的消息,在还没确认消费之前,在管理控制台还是可以看见这些消息的,但是不会再分配给其他消费者,此时这些消息的状态应该算作“已分配未消费”,如果消息最后被消费,则会在服务器端被删除,如果消费者崩溃,则这些消息会被重新分配给新的消费者。但是如果消费者既不消费确认,又不崩溃,那这些消息就永远躺在消费者的缓存区里无法处理。更通常的情况是,消费这些消息非常耗时,你开了10个消费者去处理,结果发现只有一台机器吭哧吭哧处理,另外9台啥事不干。
5.死信队列。
如果你想在消息处理失败后,不被服务器删除,还能被其他消费者处理或重试,可以关闭AUTO_ACKNOWLEDGE,将ack交由程序自己处理。那如果使用了AUTO_ACKNOWLEDGE,消息是什么时候被确认的,还有没有阻止消息确认的方法?有!
消费消息有2种方法,一种是调用consumer.receive()方法,该方法将阻塞直到获得并返回一条消息。这种情况下,消息返回给方法调用者之后就自动被确认了。另一种方法是采用listener回调函数,在有消息到达时,会调用listener接口的onMessage方法。在这种情况下,在onMessage方法执行完毕后,消息才会被确认,此时只要在方法中抛出异常,该消息就不会被确认。那么问题来了,如果一条消息不能被处理,会被退回服务器重新分配,如果只有一个消费者,该消息又会重新被获取,重新抛异常。就算有多个消费者,往往在一个服务器上不能处理的消息,在另外的服务器上依然不能被处理。难道就这么退回--获取--报错死循环了吗?
在重试6次后,ActiveMQ认为这条消息是“有毒”的,将会把消息丢到死信队列里。如果你的消息不见了,去ActiveMQ.DLQ里找找,说不定就躺在那里。
————————————————
版权声明:本文为CSDN博主「璀璨_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/soulmate_p/article/details/81380937
消息队列 折腾ActiveMQ时遇到的问题和解决方法的更多相关文章
- 工业物联网或系统集成中应用消息队列(ActiveMQ,C#的demo)的场景全面分析
1.[连载]<C#通讯(串口和网络)框架的设计与实现> 2.[开源]C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 2.应用SuperIO(SIO)和开源跨平台物联网框 ...
- 一、消息队列之ActiveMQ的安装、配置和C#样例代码
最近有时间了,研究一下消息队列ActvieMQ,结合自己的实践和网上的一些大家内容,整理如下,所有步骤和链接均是正确的. 1.ActiveMQ ActiveMQ 是Apache出品,最流行的,能力强劲 ...
- linux下安装Oracle时交换空间不足的解决方法
摘:linux下安装Oracle时交换空间不足的解决方法 linux上安装Oracle时交换空间不足的解决办法 增加交换空间有两种方法: 严格的说,在系统安装完后只有一种方法可以增加swap,那就是本 ...
- 使用WebLogic时控制台输出中文乱码解决方法
使用WebLogic时控制台输出中文乱码解决方法 1.找到weblogic安装目录,当前项目配置的domain 2.找到bin下的setDomainEnv.cmd文件 3.打开文件,从文件最后搜索第一 ...
- Apache commons StringUtils 在运行时出现NoClassDefError错误的解决方法
Apache commons StringUtils 在运行时出现NoClassDefError错误的解决方法 在用tomcat运行WEB项目,并且使用了StringUtils包的时候,会出现 jav ...
- JDBC插入数据时中文变为问号的解决方法
JDBC插入数据时中文变为问号的解决方法 制作人:全心全意 出现中文变问号的代码: String url = "jdbc:mysql://localhost:3306/test"; ...
- 通过EF操作Sqlite时遇到的问题及解决方法
1.使用Guid作为字段类型时,能存,能查,但是作为查询条件时查询不到数据 解决方法:连接字符串加上;binaryguid=False
- Windows Server环境下消息队列之ActiveMQ实战
环境准备 1.安装jdk1.7+ 2.下载新版ActiveMQ http://activemq.apache.org/ 3.启动activemq服务 4.启动成功后的界面是 5.启动成功后 浏览器访 ...
- 消息队列之 ActiveMQ(山东数漫江湖)
简介 ActiveMQ 特点 ActiveMQ 是由 Apache 出品的一款开源消息中间件,旨在为应用程序提供高效.可扩展.稳定.安全的企业级消息通信. 它的设计目标是提供标准的.面向消息的.多语言 ...
随机推荐
- 使用IDEA创建Maven项目
一.创建一个普通的Maven项目 1.启动IDEA 2.创建一个Maven项目 3.Maven的目录结构 二.使用模板创建一个MavenWeb项目 1.启动IDEA 2.创建一个MavenWeb项目 ...
- 自动化工具之Appium工具简单介绍
背景 自动化,性能测试,接口测试,开发平台等工作,到底测试的价值在哪里,其实价值来源不断充实与为大众服务,今天简单介绍ui小工具appium攻击. 简单介绍 Appium 是一个自动化测试开源工具,支 ...
- Task04:集合运算
4.1 表的加减法 4.1.1 什么是集合运算 集合在数学领域表示"各种各样的事物的总和", 在数据库领域表示记录的集合. 具体来说,表.视图和查询的执行结果都是记录的集合, 其中 ...
- 【题解】P2854 [USACO06DEC]牛的过山车Cow Roller Coaster
P2854 [USACO06DEC]牛的过山车Cow Roller Coaster 题目描述 The cows are building a roller coaster! They want you ...
- 【floyd】8.29题解-path
path 题目描述 这次的任务很简单,给出了一张有N个点M条边的加权有向无环图,接下来有Q个询问,每个询问包括2个节点X和Y,要求算出从X到Y的一条路径,使得密度最小(密度的定义为,路径上边的权值和除 ...
- 重新整理 .net core 实践篇—————HttpClientFactory[三十二]
前言 简单整理一下HttpClientFactory . 正文 这个HttpFactory 主要有下面的功能: 管理内部HttpMessageHandler 的生命周期,灵活应对资源问题和DNS刷新问 ...
- 即时通信之 SignalR
即时通信在日常的web开发场景中经常使用,本篇主要回顾一下SignalR的实现原理和通过例子说明如何在.NET Core 中使用. SingnalR 应用 需要从服务器进行高频更新的应用程序.例如游戏 ...
- Unity3D学习笔记2——绘制一个带纹理的面
目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...
- 15、docker
15.0.服务器使用说明: 服务器名称 ip地址 controller-node1 172.16.1.90 15.1.docker介绍: 1.Docker 是一个开源的应用容器引擎,基于 Go 语言 ...
- Exponentiation java大数
Exponentiation 大数a的n次幂,直到读到EOF(文件结尾)为止,其中忽略小数后面的0 1 import java.util.*; 2 import java.math.*; 3 impo ...