召唤activeMQ大神,数据丢失!!!!!!
需求如下:
需求1,队列之间资源独立,不能因为某个队列消费缓慢导致其生产者生产的消息累计,将内存/硬盘耗尽使其它队列不能使用,所以需要配置指定每个队列的资源大小,互不影响;
需求2,使用异步发送方式,加快生产消息速度,经测试持久化消息(默认同步发送)与非持久化消息(默认异步发送)速度相差一个数量级,非持久化方式符合需求;
需求3,使用非持久化消息(异步发送方式),在activeMQ服务器不出问题的情况下,不允许丢失数据。
测试发现的问题:
异步发送非持久化信息的时候,使用内存游标方式<vmQueueCursor>将非持久化消息放到内存中,并使用流量控制,配置单个队列最大内存大小为50MB,在<systemUsage>中配置sendFailIfNoSpaceAfterTimeOut=5000,在单个队列内存达到限制时(此时没有开启消费者)按理生产者应该报内存不足异常或者阻塞,但是测得生产者没有报异常,只是产生阻塞,且继续缓慢发送,为啥?
如果接着开启消费者,按理消息将被消费,内存得到缓解,生产者会继续发送消息,但是测得最终收到的消息与发送的消息总数不等,消息丢失,如何解决?
分析如下:
当使用异步发送消息(非持久化消息默认使用异步发送)时,activeMQ可能不会进行ack确认,导致生产者无法得知队列内存耗尽无法报错,但是不应该出现消息丢失啊,难道内存用尽时存在处理BUG导致消息丢失?
进一步分析:
依据以上分析,当队列内存到达限制(50MB),生产者会阻塞但继续缓慢发送消息直至最终完全堵塞,查询资料使用setProducerWindowSize()对生产者“获得ack前”能够发送的消息量进行限制,推测此功能可打开异步发送批量ack确认功能,这里设置为setProducerWindowSize(1024)。从新测试,当生产者消息堵塞,然后开启消费者消费消息,按理说内存会得到恢复,生产者继续发送消息,但是测得生产者不能继续发送消息,生产者和消费者均不能允许貌似互锁,为啥?
本人一直尝试各种配置,并未找到一种高效并且不会丢失消息的方案,因此求助版面各位大神推荐一种好的配置,难道是activeMQ的BUG?
如果是BUG请英文好的大神帮忙提交到activeMQ开源社区,万分感谢,急等中ing。
附上测试程序与配置文件:
生产者代码:(运行时开启一个线程调用它即可)
public class Sender implements Runnable {
int threadId;
public Sender(int threadId) {
this.threadId = threadId;
}
@Override
public void run() {
try {
String user = "admin";
String password = "activemq";
String url = "tcp://192.168.18.151:61616";
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( user, password, url);
//配置AlwaysSyncSend,非持久化在资源耗尽的时候将得到通知,虽然速度会变慢.
connectionFactory.setProducerWindowSize(1024);
connectionFactory.setSendAcksAsync(true);//这个方法有什么用?
// connectionFactory.setAlwaysSyncSend(true);//同步
// connectionFactory.setProducerWindowSize(1024*1024);
connectionFactory.setUseAsyncSend(true);//异步
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("test."+this.threadId);
MessageProducer producer = session.createProducer(destination);
Date date = new Date();
long t1 = date.getTime();
System.out.println("connThread"+threadId+" 开始时间:"+new Date());
int p = 0;
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
for (int i = 0; i < 100000; i++) {
TextMessage message = session.createTextMessage();
message.setText(Integer.toString(i));
//Thread.sleep(1);
try {
producer.send(message);
p++;
if(p%1000 == 0){
// session.commit();
System.out.println("connThread"+threadId+" 已发送:"+p+"条,用时:"+(new Date().getTime() - t1));
}
// System.out.println("connThread"+threadId+" 已发送:"+p+"条,用时:"+(new Date().getTime() - t1));
} catch (Exception e) {
e.printStackTrace();
}
// session.commit();
//System.out.println("--发送消息:" + date);
}
System.out.println("connThread"+threadId+" 共发送"+p+"条,结束时间:"+new Date());
// System.out.println("connThread"+threadId+" 共用时:"+(new Date().getTime() - t1));
//session.commit();
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}消费者代码:public class ConnConsumer {
public static int threadId = 0;
public static void main(String[] args) throws JMSException, InterruptedException{
for(int i=0; i<15; i++){
ConnConsumer.receive(threadId++);
}
Thread.sleep(3*24*60*60*1000);
}
public static void receive(int threadId) throws InterruptedException{
try {
String user = "admin";
String password = "activemq";
String url = "tcp://192.168.18.151:61616"; //
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( user, password, url);
//异步分发,当使用listener时是异步,receive是同步
// connectionFactory.setDispatchAsync(true);
Connection connection = connectionFactory.createConnection();
connection.start();
final Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("TEST."+threadId);
MessageConsumer message = session.createConsumer(destination);
message.setMessageListener(new MsgListener(threadId));
//Thread.sleep(3*24*60*60*1000);
//session.close();
//connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}public class MsgListener implements MessageListener {
int threadId;
int count = 0;
Date date = new Date();
long t1 = date.getTime();
int sum = 0;
public MsgListener(int threadId) {
System.out.println("threadId:"+threadId+"启动监听");
this.threadId = threadId;
}
@Override
public void onMessage(Message msg) {
TextMessage message = (TextMessage) msg;
// try {
// sum += Integer.parseInt(message.getText());
// } catch (NumberFormatException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (JMSException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//System.out.println("--收到消息:" + new Date(message.getLong("count")));
count ++;
if(count%1000 == 0){
System.out.println("connThread"+threadId+" 接收:"+count+"条,用时:"+(new Date().getTime() - t1));
}else if(count == 1){
System.out.println("connThread"+threadId+" 开始时间:"+new Date());
}
// System.out.println("sum is " + sum);
//session.commit();
}
}配置文件:….
<policyEntry queue=">" producerFlowControl="true" memoryLimit="50mb">
<!-- 使用VM游标,非持久化消息放在内存中,达到指定内存后停掉生产者-->
<pendingQueuePolicy>
<vmQueueCursor/>
<pendingQueuePolicy>
</policyEntry>
….
<systemUsage>
<!-- 当资源耗尽时,生产者阻塞5秒后,API报错-->
<systemUsage sendFailIfNoSpaceAfterTimeOut="5000">
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
…相关推荐
JEP30-PX100A PartModel Product Guidelines for Electronic-Device Substrates and Assemblies – XML Requ
JEP30-PX100A PartModel Product Guidelines for Electronic-Device Substrates and Assemblies – XML Requirements
基于Matlab的自动睡眠粒状结构检测算法,从脑电信号中进行。.zip
1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
JEP375 2.5D_3D Silicon thinned wafers with Through Silicon Vias (TSV’s) and Backside Redistribution
JEP375 2.5D_3D Silicon thinned wafers with Through Silicon Vias (TSV’s) and Backside Redistribution Layer (RDL).pdf
考虑供电可靠性与算力柔性的数据中心园区源‑储‑荷一体化规划研究(Matlab代码实现)
考虑供电可靠性与算力柔性的数据中心园区源‑储‑荷一体化规划研究(Matlab代码实现)内容概要:本文围绕“考虑供电可靠性与算力柔性的数据中心园区源-储-荷一体化规划”展开研究,提出了一种综合能源系统优化规划方法。该方法充分考虑数据中心对供电可靠性的高要求以及算力负载的灵活性特征,将电力供应、储能配置与计算负荷进行协同优化。通过建立数学模型,整合光伏发电、储能系统与数据中心负荷调度,利用Matlab代码实现优化求解,旨在提升能源利用效率、降低运营成本并增强系统韧性。研究涵盖了对新能源出力不确定性、负荷波动以及储能动态行为的建模与仿真分析,最终验证了所提一体化规划方案在提高供电可靠性和实现算力资源柔性调度方面的有效性。; 适合人群:具备一定电气工程、能源系统或计算机科学背景,从事数据中心、智能电网、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 为数据中心园区的绿色低碳与高可靠运行提供规划设计方案;② 实现可再生能源的高效消纳与储能系统的优化配置;③ 探索算力作为柔性负荷参与电力系统互动的潜力,支撑新型电力系统建设。; 阅读建议:此资源以Matlab代码为核心,辅以理论模型,建议读者在理解基本原理的基础上,动手运行和调试所提供的代码,通过修改参数和场景设置来深入掌握一体化规划的优化逻辑与关键技术细节。
歌曲爆款传播预测数据集10000首曲目Spotify音频特征机器学习
本数据集为合成音乐数据,包含2010至2025年间10000首曲目的Spotify风格音频特征与明确的爆款(viral)目标标签。现有音乐数据集常缺少可用建模目标或存在授权限制,本数据集提供了干净、字段完整、可直接用于监督学习的基准语料。字段涵盖节奏、能量、可舞性、声学度、效价等音频属性,以及曲目元数据与年份信息,目标列viral基于传播表现定义,可直接用于二分类建模。适合开展爆款歌曲预测、音频特征与传播关系分析、年代音乐风格演变可视化、特征重要性排序等分析任务,也可作为分类、回归与特征工程教学的演示数据。数据结构清晰、无缺失值,适合数据科学课程、音乐媒体分析与推荐算法原型验证使用。


