我们遇到的问题是,有多个异步线程处理大量数据,需要几分钟甚至几个小时才能结束。
在这种情况下,我们希望线程在短期内完成它们的工作,并留下一个状态,我们可以使用它来处理剩余的数据。
我们已经使用了graceful.shutdown=enable
。
现在的想法是,我们在创建异步线程的bean中引入一个带有@PreDestroy
的方法。当这个方法被调用时,它将在另一个bean中设置一个“shutdown”标志。所有长时间运行的线程在处理过程中都会检查这个标志,当它为真时将停止处理,并将它们处理的干净状态写入数据库。
这或多或少是有效的...但不是所有的时间。
正如我在第一次得到shutdown触发器后所理解的那样,有一个可配置的时间spring.lifecycle.timeout-per-shutdown-phase
,在这个时间内线程可以继续处理它们的工作,而不会减少任何所需的资源。在这个时间过后,所有的shutdownhook都会以未知的顺序处理。这让我想到,我可能没有离开干净状态所必需的所有资源。当我使用@preDestroy
和标志的方法时。
有没有更好的解决办法?
是否需要向线程(如setAwaitTerminationSeconds(60);
或setWaitForTasksToCompleteOnShutdown(true);
)添加更多配置?
1条答案
按热度按时间ru9i0ody1#
我发现,当在Spring中使用
graceful.shutdown=enable
和@PreDestroy
时,需要对synchronize
、run()
方法和@PreDestroy
方法(前提是这两个方法在同一个类中):你需要确保你的
run()
方法没有做任何事情,当preDestroy()
已经被调用时,因此shutdown
-标志。synchronize
的作用是,preDestroy()
会自动等待,直到run()
定期结束。只有在preDestroy()
结束时,preDestroy()
才会被调用。通过设置shutDown
标志,它可以防止启动另一个长时间运行的线程,即使run()
再次被调用。相反,run()
会立即返回。因为否则的话,当你不同步的时候,在spring服务器得到一个
shutdown
信号之后,preDestroy()
会被立即调用,但是springthinks
如果preDestroy()
已经运行并且成功完成,它会立即关闭自己。这不是你想要的,因为这样所有的run()
线程都会被中断。我还发现,当使用
@Scheduled
-注解(而不是在构造函数中调用taskScheduler.scheduleWithFixedDelay(this, 100)
)时,上面的例子不工作。