mqtt消费堆积

mqtt发送主题成功,但消费主题只有一个

代码实例:

java 复制代码
    @ServiceActivator(inputChannel = "caGetConfig")
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        try {
            String payload = (String) message.getPayload();
            String topic = (String) message.getHeaders().get(MQTTRECEIVEDTOPIC);
            log.info("接收到MQTT消息,主题: {}, 消息内容: {}", topic, payload);
            try {
                if (StringUtils.isEmpty(payload)) {
                    log.info("接收到空的MQTT消息,主题: {}", topic);
                    CompletableFuture.runAsync(() -> generateVideoService.getNeMessage());
                    return;
                }
                if (StringUtils.isBlank(topic)) {
                    log.info("接收到空的MQTT消息,主题: {}", topic);
                    CompletableFuture.runAsync(() -> generateVideoService.getNeMessage());
                }
                // 处理MQTT消息
                List<String> onlineStatusNewLis = JSON.parseArray(payload, String.class);
                if (CollectionUtils.isNotEmpty(onlineStatusNewLis)){
                    generateVideoService.getNeMessageByUrl(onlineStatusNewLis)
                }
            } catch (Exception e) {
                log.error("分发MQTT消息失败,主题: {}, 消息: {}", topic, payload, e);
            }
        } catch (Exception e) {
            log.error("处理MQTT消息失败,消息: {}", message, e);
        }
    }

问题分析:

1. MQTT 消费者是单线程的

@ServiceActivator(inputChannel = "caGetConfig") 基于 Spring Integration MQTT,其 inputChannel 默认是 PublishSubscribeChannel(同步调用),即消息的接收和处理在同一线程中串行执行。只有当 handleMessage() 方法返回后,才能处理下一条消息。

2. 使用 CompletableFuture.runAsync 异步调用

generateVideoService.getNeMessageByUrl(onlineStatusNewLis);方法执行完才能返回。如果 onlineStatusNewLis 列表较大,或者数据库查询较慢,这段时间内 MQTT 消费线程就会被阻塞。

如果该方法里面是一个 while(!Thread.currentThread().isInterrupted()) 的无限循环 ,这个循环会在 MQTT 消费线程上执行,永远无法返回,后续所有消息都将被彻底阻塞。

添加异步编排执行,解决阻塞

java 复制代码
// 处理MQTT消息
List<String> onlineStatusNewLis = JSON.parseArray(payload, String.class);
if (CollectionUtils.isNotEmpty(onlineStatusNewLis)){
  CompletableFuture.runAsync(() -> generateVideoService.getNeMessageByUrl(onlineStatusNewLis));
                    
}
相关推荐
程序员黑豆3 小时前
Java包装类:基本类型与对象的桥梁
java·前端·ai编程
mldong6 小时前
"applicant" 契约:退回发起人的闭环设计
java·架构
月华路7 小时前
G1 垃圾回收:脏卡队列、记忆集与并发精化线程机制
java·开发语言
gugucoding7 小时前
47. 【Java】Java内存模型(JMM)与可见性
java·开发语言
zww89491118 小时前
校园跑腿系统开发实战指南:从需求分析到上线部署全流程解析
java
Fluxart.ai8 小时前
电商商品图审核怎么自动化?规则引擎、人工复核与发布门禁
java·前端·自动化
sudebao点com9 小时前
一次“Google 能打开,FlexTV 打不开”的 DNS 故障排查:从 curl 超时到完整证据链
windows·macos·https·cdn·dns·nslookup·网络排错
名字还没想好☜9 小时前
Java 线上内存泄漏排查实战:jmap 导堆、MAT 找 GC Roots 与四类常见泄漏
java·开发语言·jvm·内存泄漏
IT爱学堂10 小时前
尚硅谷 - 2025年3月Java+AI大模型应用开发
java·开发语言·人工智能
小贤plus11 小时前
SpringBoot 三大核心注解精讲:@ControllerAdvice、@RestControllerAdvice、@Validated 分组校验(实战)
java