Mono.timeout立即触发超时问题求助
排查Mono超时总是触发的可能原因
从几个核心方向逐一排查:
确认消息是否真的在超时窗口内到达
先跳出代码逻辑,直接验证JMS消息的时序:在消息发送端打日志记录发送时间;在msgProcessor.registerListener的回调逻辑(也就是sink::success被调用的地方)打日志记录消息到达时间。如果消息到达时间确实超过10秒,那超时属于正常触发,需要优化消息传输链路或延长超时时长。检查
registerListener是否正确触发sink.success()
这是最常见的问题根源:- 核对
requestId是否完全匹配,有没有大小写、格式错误,导致监听器监听的目标消息根本没被路由过来; - 查看
registerListener内部实现,是否存在消息过滤、异常吞吃等情况,导致消息到达后没调用到传入的sink.success()。比如监听器代码里的try-catch块吞了异常,让回调逻辑直接静默失败,Mono就会一直处于未完成状态,直到超时。
- 核对
验证线程调用是否正常
虽然MonoSink本身是线程安全的,但如果JMS监听器在特殊线程(比如JMS客户端的守护线程)中调用sink.success(),可以加日志确认回调是否真的被执行。另外排查是否有线程阻塞情况:比如监听器收到消息后做了耗时同步操作,导致sink.success()调用延迟超过10秒。排除
doFinally的干扰(非超时原因,但可能影响测试判断)
超时触发后doFinally会移除requestId对应的监听器,如果此时消息刚好到达,监听器已经被移除,会误以为消息没按时到达。可以先注释掉doFinally的逻辑,测试超时是否还会触发,排除这个干扰项。
代码调试建议
给关键环节加日志,清晰追踪流程:
Mono result = Mono.create(sink -> { System.out.println("监听器注册完成,requestId: " + requestId); msgProcessor.registerListener(response -> { System.out.println("收到JMS消息,requestId: " + requestId + ",内容: " + response); sink.success(response); }, requestId); }) .timeout(Duration.ofSeconds(10)) .onErrorReturn(msgProcessor.timeout()) .doFinally(change -> { System.out.println("执行doFinally,移除requestId: " + requestId + ",信号类型: " + change); msgProcessors.remove(requestId); });
通过日志就能明确是消息未到达、回调未触发,还是触发延迟导致的超时。
内容的提问来源于stack exchange,提问作者laserman999
相关产品推荐
相关产品推荐

