解决:com.atomikos.icatch.SysException: Error in init: Log already in use? tmlog in ./

项目场景

Spring Boot 2.x,集成 atomikos

问题描述

今天在同一个环境启动两个项目时报错,因为两个项目同时涉及到分布式事物和切换数据源相关。
项目集成atomikos后,

org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.transaction.UserTransaction]: Factory method 'userTransaction' threw exception; nested exception is com.atomikos.icatch.SysException: Error in init: Log already in use? tmlog in ./
 org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
 org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)\n\t... 25 common frames omitted\nCaused by: com.atomikos.icatch.SysException: Error in init: Log already in use? tmlog in ./
 com.atomikos.icatch.provider.imp.AssemblerImp.createRepository(AssemblerImp.java:181)
 com.atomikos.icatch.provider.imp.AssemblerImp.assembleTransactionService(AssemblerImp.java:156)
 com.atomikos.icatch.config.Configuration.assembleSystemComponents(Configuration.java:485)
 com.atomikos.icatch.config.Configuration.init(Configuration.java:448)
 com.atomikos.icatch.config.UserTransactionServiceImp.initialize(UserTransactionServiceImp.java:105)
 com.atomikos.icatch.config.UserTransactionServiceImp.init(UserTransactionServiceImp.java:219)
 com.atomikos.icatch.jta.UserTransactionImp.checkSetup(UserTransactionImp.java:59)
 com.atomikos.icatch.jta.UserTransactionImp.setTransactionTimeout(UserTransactionImp.java:127)
 ...

原因分析

在项目中使用atomikos时,如果在同一个环境中部署两个以上这种项目,则可能会报出com.atomikos.icatch.SysException: Error in init(): Log already in use异常,
这个信息是因为atomikos在默认情况下是将console_file_name和log_base_name设置为默认值:tm.out和tmlog0.log,并且会将这两个文件上锁,导致其他线程无法访问,所以当多个项目都未指定这一名称时就会出现上述异常信息。

详细分析

例如,在com.atomikos下的 transactions-4.0.6.jar 包里,有一个类:com.atomikos.icatch.provider.imp.AssemblerImp.java

部分代码如下:

public ConfigProperties initializeProperties() {
    
    
    Properties defaults = new Properties();
    this.loadPropertiesFromClasspath(defaults, "transactions-defaults.properties");
    Properties transactionsProperties = new Properties(defaults);
    this.loadPropertiesFromClasspath(transactionsProperties, "transactions.properties");
    Properties jtaProperties = new Properties(transactionsProperties);
    this.loadPropertiesFromClasspath(jtaProperties, "jta.properties");
    Properties customProperties = new Properties(jtaProperties);
    this.loadPropertiesFromCustomFilePath(customProperties);
    Properties finalProperties = new Properties(customProperties);
    ConfigProperties configProperties = new ConfigProperties(finalProperties);
    this.checkRegistration(configProperties);
    return configProperties;
}

从内部实现,可以看出是,首先会加载transactions-defaults.properties文件,后面会去加载自定义配置文件(customProperties),即jta.properties文件。所以思路就是重新指定不同的文件名;

解决方案

在每一个项目中都指定atomikos的文件名称:
在受影响的项目里,新建一个jta.properties文件,添加配置如下:里面属性的值,保证每个项目的名称都不一样

com.atomikos.icatch.log_base_name=service1-tmlog

猜你喜欢

转载自blog.csdn.net/u014163312/article/details/129940818