首页 > 解决方案 > Atomikos 事务超时和春季重试

问题描述

我们正在使用 atomikos 进行分布式事务管理。对于非常大的文件处理,我可以在进程开始后 300 秒在日志中看到以下条目。

  "message" : "Transaction xxxxxxxx.tm123 has timed out and will rollback.",
  "logger_name" : "com.atomikos.icatch.imp.ActiveStateHandler",
  "thread_name" : "Atomikos:1234",

我们已将超时设置为 300 秒。com.atomikos.icatch.default_jta_timeout=300000

但是对于需要将每一行保存到数据库的非常大的文件(一年一次),即使在 300 秒后它也会继续保存到表中。进程结束大约 30 分钟后,我们可以在几毫秒内看到数千次日志文件中的以下警告。

  "message" : "Forcing close of pending statement: oracle.jdbc.driver.OraclePreparedStatementWrapper",
  "logger_name" : "com.atomikos.jdbc.AbstractConnectionProxy",

使用重试机制的 Rest 服务org.springframework.retry.annotation.Retryable再次运行,但这次由于 Hibernate 缓存而运行得更快。但是重试有副作用,比如部分过程会像发送文件一样运行两次,从而导致一些问题。我已经实现了一个基本的解决方案,比如维护标志是否正在发送文件,或者在事务管理级别寻找更好的解决方案。

有没有人遇到过与atomikos类似的问题?你是怎么处理的呢

下面是休息服务代码。我们没有看到它进入异常块,因为在日志中没有看到错误。尚未尝试将 @Transactional 移动到 mainProcess() 方法。

@RequestMapping("someProcess/")
@Transactional
@Retryable(
        include = {Exception.class, JpaSystemException.class, IOException.class},
        maxAttemptsExpression = "#{${retry.maxAttempts}}",
        backoff = @Backoff(
                delayExpression = "#{${retry.retryDelay}}",
                maxDelayExpression = "#{${retry.maxDelay}}",
                multiplierExpression = "#{${retry.multiplier}}"
        )
)
public void someProcess() throws Exception {

    try {
        mainProcess();  
    } catch (Exception e) {
        logError(e);
        throw e;
    }

我们正在使用 atomikos 4.0.6 和 spring boot 2.1.4。

标签: jtadistributed-transactionsspring-retryatomikostransactionmanager

解决方案


推荐阅读