Spring Integration SFTP定时Flow随机重复执行问题排查
结合你的配置和现象,除了Cron轮询适配器外,以下因素可能导致Flow被额外触发:
maxMessagesPerPoll配置导致的同轮询任务内批量执行
你设置了maxMessagesPerPoll(50),而你的消息源() -> new GenericMessage<>("/a-remote-directory")每次调用都会生成一条新消息。这意味着每次Cron触发的轮询任务中,框架会连续从消息源读取最多50次消息,每次都触发完整的Flow执行。这种批量处理会在Cron时间点之后的一段时间内产生大量连续执行记录,看起来像是随机时间触发,但实际属于同一轮询任务的范围。自定义
PollSkipAdvice的逻辑漏洞
你的DatabasePollSkipStrategy决定是否跳过轮询,如果其shouldSkipPoll()方法存在逻辑错误(比如数据库状态判断不准确、状态未正确更新),可能导致框架在非Cron时间点错误地允许轮询执行,进而触发Flow。线程池任务调度器的异常任务提交
你使用了自定义的ThreadPoolTaskScheduler作为Poller的任务执行器,如果调度器内部线程管理出现问题(比如线程未正确终止、任务被重复提交到队列),可能导致Flow任务被额外调度执行。Splitter组件的线程复用与消息循环
Flow中两次使用split()拆分消息,当拆分出的消息数量较多时,线程池中的线程在完成单条消息处理后,可能被框架复用去处理同一轮询任务中的下一条消息。如果消息源的逻辑存在隐含的循环(比如每次处理后又生成新的触发消息),也会导致Flow重复执行。
排查建议
- 临时将
maxMessagesPerPoll改为1,观察是否还会出现随机时间的执行,验证是否是批量处理导致的现象。 - 检查
DatabasePollSkipStrategy的shouldSkipPoll()方法逻辑,确保其能准确判断是否允许轮询,重点排查数据库状态读取和更新的正确性。 - 监控
ThreadPoolTaskScheduler的线程状态(活跃线程数、任务队列长度),查看是否有异常的任务提交情况。 - 启用Spring Integration消息跟踪(配置
spring.integration.message-tracking.enabled=true),追踪每个Flow执行的触发源,确认执行是否来自Cron调度。
内容的提问来源于stack exchange,提问作者st.

