ActiveMQ服务挂掉怎么办

折腾ActiveMQ时遇到的问题和解决方法:

1.先讲严重的:服务挂掉。

这得从ActiveMQ的储存机制说起。在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的,它们的最大限制在配置文件的<systemUsage>节点中配置。但是,在非持久化消息堆积到一定程度,内存告急的时候,ActiveMQ会将内存中的非持久化消息写入临时文件中,以腾出内存。虽然都保存到了文件里,但它和持久化消息的区别是,重启后持久化消息会从文件中恢复,非持久化的临时文件会直接删除。

那如果文件增大到达了配置中的最大限制的时候会发生什么?我做了以下实验:

设置2G左右的持久化文件限制,大量生产持久化消息直到文件达到最大限制,此时生产者阻塞,但消费者可正常连接并消费消息,等消息消费掉一部分,文件删除又腾出空间之后,生产者又可继续发送消息,服务自动恢复正常。

设置2G左右的临时文件限制,大量生产非持久化消息并写入临时文件,在达到最大限制时,生产者阻塞,消费者可正常连接但不能消费消息,或者原本慢速消费的消费者,消费突然停止。整个系统可连接,但是无法提供服务,就这样挂了。

具体原因不详,解决方案:尽量不要用非持久化消息,非要用的话,将临时文件限制尽可能的调大。

详细配置信息见文档: http://activemq.apache.org/producer-flow-control.html

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()方法会负责任的等待服务器的返回,也就不会关闭连接导致消息丢失了。

关于java.net.SocketException请看我的详细研究: http://blog.163.com/_kid/blog/static/3040547620160231534692/

3.持久化消息非常慢。

默认的情况下,非持久化的消息是异步发送的,持久化的消息是同步发送的,遇到慢一点的硬盘,发送消息的速度是无法忍受的。但是在开启事务的情况下,消息都是异步发送的,效率会有2个数量级的提升。所以在发送持久化消息时,请务必开启事务模式。其实发送非持久化消息时也建议开启事务,因为根本不会影响性能。

4.消息的不均匀消费。

有时在发送一些消息之后,开启2个消费者去处理消息。会发现一个消费者处理了所有的消息,另一个消费者根本没收到消息。原因在于ActiveMQ的prefetch机制。当消费者去获取消息时,不会一条一条去获取,而是一次性获取一批,默认是1000条。这些预获取的消息,在还没确认消费之前,在管理控制台还是可以看见这些消息的,但是不会再分配给其他消费者,此时这些消息的状态应该算作“已分配未消费”,如果消息最后被消费,则会在服务器端被删除,如果消费者崩溃,则这些消息会被重新分配给新的消费者。但是如果消费者既不消费确认,又不崩溃,那这些消息就永远躺在消费者的缓存区里无法处理。更通常的情况是,消费这些消息非常耗时,你开了10个消费者去处理,结果发现只有一台机器吭哧吭哧处理,另外9台啥事不干。

解决方案:将prefetch设为1,每次处理1条消息,处理完再去取,这样也慢不了多少。

详细文档: http://activemq.apache.org/what-is-the-prefetch-limit-for.html

5.死信队列。

如果你想在消息处理失败后,不被服务器删除,还能被其他消费者处理或重试,可以关闭AUTO_ACKNOWLEDGE,将ack交由程序自己处理。那如果使用了AUTO_ACKNOWLEDGE,消息是什么时候被确认的,还有没有阻止消息确认的方法?有!

消费消息有2种方法,一种是调用consumer.receive()方法,该方法将阻塞直到获得并返回一条消息。这种情况下,消息返回给方法调用者之后就自动被确认了。另一种方法是采用listener回调函数,在有消息到达时,会调用listener接口的onMessage方法。在这种情况下,在onMessage方法执行完毕后,消息才会被确认,此时只要在方法中抛出异常,该消息就不会被确认。那么问题来了,如果一条消息不能被处理,会被退回服务器重新分配,如果只有一个消费者,该消息又会重新被获取,重新抛异常。就算有多个消费者,往往在一个服务器上不能处理的消息,在另外的服务器上依然不能被处理。难道就这么退回--获取--报错死循环了吗?

在重试6次后,ActiveMQ认为这条消息是“有毒”的,将会把消息丢到死信队列里。如果你的消息不见了,去ActiveMQ.DLQ里找找,说不定就躺在那里。

详细文档: http://activemq.apache.org/redelivery-policy.html

http://activemq.apache.org/message-redelivery-and-dlq-handling.html

时间: 2024-11-06 07:33:40

ActiveMQ服务挂掉怎么办的相关文章

mongodump 失败且导致mongo服务挂掉

问题阐述: mongodb版本3.2.7(yum安装) 需要mongodump出一个collection 如下 mongodump --collection abc --db db abc 为接近2亿条,单条大概200B 每次执行mongodum命令,进度到52.5%就会报错如下,并且mongo服务挂掉,必须重启 2017-05-02T17:08:51.663+0800 [############............] db.abc 91363661/177602822 (51.4%) 20

php-fpm服务挂掉

今天发了个链接,可能同时在线的人瞬间比较多,结果网站报503错误,回去打开php-fpm错误日志一看,php-fpm服务挂掉了,报如下错误: [04-Apr-2016 15:38:04] NOTICE: systemdmonitorintervalsetto 10000ms [05-Apr-2016 19:03:08] WARNING: [poolwww] seemsbusy (youmayneedto increasepm.start_servers, or pm.min/max_spare_

ActiveMQ服务安装

1.下载安装ActiveMQ服务提供者 http://activemq.apache.org/ 2.启用ActiveMQ服务 cd [activemq_install_dir] bin\activemq 3.验证服务 netstat -an|find "61616" 4.ActiveMQ的控制台查看 http://localhost:8161/admin 5.关闭ActiveMQ "CTRL-C" in the console or command shell in

搭建spring boot+elasticsearch+activemq服务

目前时间是:2017-01-24 本文不涉及activemq的安装 需求 activemq实时传递数据至服务 elasticsearch做索引 对外开放查询接口 完成全文检索 环境 jdk:1.8 spirng boot:1.4.3.RELEASE elasticsearch:2.4.3 activemq:5.13.2 ES插件 head:版本好像无太大差别 能查数据就行 analysis-ik:1.10.3 search-guard-2:2.4.3.9 search-guard-ssl:2.4

Activemq服务无法启动的报错及原因总结

前言 环境说明:系统版本:centos7.3activemq版本:apache-activemq-5.14.5 1.主机hostname有非法字符 修改主机hostname的时候,不小心写入了非法字符,如下划线"_",导致服务启动失败.报错内容: 2019-09-29 12:44:42,057 | ERROR | Failed to start Apache ActiveMQ ([localhost, ID:193_168_0_24-43901-1569732279834-0:1],

Redis服务挂掉后,重启时闪退

这个时候去进程管理器里找一个 redisservice.exe 的进程..杀死他  杀死他  杀死他!!! 整理领结,嘬口咖啡, 嗯... 然后再来启动服务.. 原文地址:https://www.cnblogs.com/iiwen/p/8117989.html

swoole服务挂掉,配合cron定时任务,自动启动

swoole常用的命令: swoole停止服务: kill -9 $(ps aux|grep 'socket.php'|grep -v grep|awk '{print $2}') 开启swoole服务压人后台命令: nohup php socket.php & screen socket.php swoole 脚本,如果服务停止,每一分钟检测自动启动,配合cron定时任务运行下边的脚本文件 #!/bin/bashcount=`ps -fe |grep "socket.php"

ActiveMQ伪分布式部署

本文借鉴http://www.cnblogs.com/guozhen/p/5984915.html,在此基础上进行了完善,使之成为一个完整版的伪分布式部署说明,在此记录一下! 一.本文目的 介绍如何在同一台虚拟机上搭建高可用的Activemq服务,集群数量包含3个Activemq,当Activemq可用数>=2时,整个集群可用. 本文Activemq的集群数量为3个,分别命名为mq1,mq2,mq3   二.概念介绍 1.伪集群 集群搭建在同一台虚拟机上,3个Activemq分别使用不同的端口提

ActiveMQ 高可用集群安装、配置(ZooKeeper + LevelDB)

1.ActiveMQ 集群部署规划: 环境: JDK7 版本:ActiveMQ 5.11.1 ZooKeeper 集群环境:10.14.0.1:2181,10.14.0.2:2182,10.14.0.3:2183(ZooKeeper 集群部署请参考<ZooKeeper 集群的安装.配置>) 主机 集群端口 消息端口 管控台端口 节点安装目录 192.168.1.11 63631 53531 8361 /opt/aijia/activemq/node-01 192.168.1.12 63632