Heroku + Spring Boot:@Scheduled没有在正确的时间运行

时间:2017-07-01 13:27:02

标签: java spring heroku spring-boot

我在Boot应用程序中有一个Spring bean,如下所示:

@Component
public class AuthTokenCleanupJob {

    private static final Logger LOGGER = LogManager.getLogger(AuthTokenCleanupJob.class);

    @Autowired
    private AuthTokenRepository authTokenRepository;

    @Transactional
    @Scheduled(fixedDelay = 300000L)
    public void cleanupTokens() {
        LOGGER.info("Deleting expired AUTH_TOKENS");
        authTokenRepository.deleteOldTokens();
        LOGGER.info("Deleted expired AUTH_TOKENS");
    }
}

并在Heroku中记录如下所示的消息:

Jun 29 06:07:28 myapp app/web.2:  2017-06-29 13:07:28.790  INFO 4 --- [pool-2-thread-1] com.myapp.jobs.AuthTokenCleanup      : Deleted expired AUTH_TOKENS 
Jun 29 14:06:04 myapp app/web.1:  2017-06-29 21:06:04.230  INFO 4 --- [pool-2-thread-1] com.myapp.jobs.AuthTokenCleanup      : Deleted expired AUTH_TOKENS 
Jun 30 06:36:25 myapp app/web.2:  2017-06-30 13:36:24.882  INFO 4 --- [pool-2-thread-1] com.myapp.jobs.AuthTokenCleanup      : Deleted expired AUTH_TOKENS 
Jun 30 14:31:16 myapp app/web.1:  2017-06-30 21:31:15.876  INFO 4 --- [pool-2-thread-1] com.myapp.jobs.AuthTokenCleanup      : Deleted expired AUTH_TOKENS 

为什么作业应该在每5分钟运行一次的时候运行?我正在为这个应用程序运行1X Professional dyno。

更新

PostgreSQL表中只有386行被清理,所以我不认为这是一个挂起的数据库。此外,它是一个非常无聊的应用程序,所以运行DBCP的连接没有任何意义我也不会想。

1 个答案:

答案 0 :(得分:2)

显然它与代理事物的方式有关。我最终将@Transactional@Scheduled拆分为两个bean并修复了问题。由于我在IntelliJ中运行本地版本而不是运行输出JAR,我猜测代理的创建方式不同(或者以不同的顺序,也许?)。无论哪种方式,它现在可以使用以下内容:

@Component
public class AuthTokenCleanupJob {

    private static final Logger LOGGER = LogManager.getLogger(AuthTokenCleanupJob.class);

    @Autowired
    private AuthTokenCleanupService authTokenCleanupService;

    @Scheduled(fixedDelay = 300000L)
    public void cleanupTokens() {
        LOGGER.info("Deleting expired AUTH_TOKENS");
        authTokenCleanupService.cleanupAuthTokens();
        LOGGER.info("Deleted expired AUTH_TOKENS");
    }
}

-

@Service
@Transactional
class AuthTokenCleanupService {

    @Autowired
    private AuthTokenRepository authTokenRepository;

    def cleanupAuthTokens() {
        authTokenRepository.deleteOldTokens();
    }

}

注意:AuthTokenCleanupService是Groovy代码。