Почему ChainedTransactionManager с установкой времени ожидания через аннотацию не работает? Весенний ботинок

Заявление:

  • Весенняя загрузочная версия 2.2.13.RELEASE
  • postgresql версии 42.2.10
  • кварц версия 2.3.2
  • кварцевая версия 2.3.2

Я реализовал кварц заданий, который вызывает метод, реализованный в bean-компоненте @Service. В этом методе есть взаимодействие с двумя базами данных (Oracle и PostgreSql). Каждая БД инициализируется пулом соединений Hikari.

БД Postgresql в bean-компоненте конфигурации:

        @Bean(value="sreDataSource")
        public DataSource dataSource() {
        
            HikariConfig hikariConfig = new HikariConfig();
            hikariConfig.setDriverClassName(driverClassName);
            hikariConfig.setJdbcUrl(datasourceUrl); 
            hikariConfig.setUsername(datasourceUsername);
            hikariConfig.setPassword(datasourcePassword);
            hikariConfig.setConnectionInitSql("set time zone 'UTC'");
            hikariConfig.setMaximumPoolSize(maxPoolSize);
            hikariConfig.setConnectionTestQuery("SELECT 1");
            hikariConfig.setPoolName("springHikariCP");
        
            return new HikariDataSource(hikariConfig);
            
        }
    /**
         * @return {@link JdbcTemplate}
         */
        @Bean(value="sreJdbcTemplate")
        public JdbcTemplate jdbcTemplate() {
            
            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
            jdbcTemplate.setFetchSize(Integer.parseInt(fetchSize));
            jdbcTemplate.setQueryTimeout(60);
            
            return jdbcTemplate;
        }
    
        
        /**
         * Create the namedJdbcTemplate bean for the SRE database
         * @return {@link NamedParameterJdbcTemplate}
         */
        @Bean(value="sreNamedParameterJdbcTemplate")
        public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
            
            return new NamedParameterJdbcTemplate(jdbcTemplate());
        }
        
        
        /**
         * @param dataSource
         * @return {@link PlatformTransactionManager}
         */
        @Bean(value="sreTransactionManager")
        public PlatformTransactionManager transactionManager(@Qualifier("sreDataSource") DataSource dataSource) {
            
            return new DataSourceTransactionManager(dataSource);
        }
/**
     * @param sreTransactionManager
     * @param assetTransactionManager
     * @return {@link ChainedTransactionManager}
     */
    @Bean(value="chainedTransactionManager")
    public ChainedTransactionManager transactionManager(@Qualifier("sreTransactionManager") PlatformTransactionManager sreTransactionManager,
                                                    @Qualifier("assetTransactionManager") PlatformTransactionManager assetTransactionManager) {
         return new ChainedTransactionManager(sreTransactionManager, assetTransactionManager);
    }

БД Oracle в bean-компоненте конфигурации:

/**
     * Datasource
     * @return Datasource
     */
    @Bean(value="assetDataSource")
    public DataSource dataSource() {
        
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(driverClassName);
        hikariConfig.setJdbcUrl(datasourceUrl); 
        hikariConfig.setUsername(datasourceUsername);
        hikariConfig.setPassword(datasourcePassword);
        hikariConfig.addDataSourceProperty("oracle.jdbc.timezoneAsRegion", "false");
        hikariConfig.setMaximumPoolSize(maxPoolSize);
        hikariConfig.setConnectionTestQuery("SELECT 1 from dual");
        hikariConfig.setPoolName("springHikariAssetCp");
        
        
        return new HikariDataSource(hikariConfig);
    }
    
    /**
     * JDBCTemplate
     * @return JDBCTemplate
     */
    @Bean(value="assetJdbcTemplate")
    public JdbcTemplate jdbcTemplate() {
        
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
        jdbcTemplate.setFetchSize(Integer.parseInt(fetchSize));
        jdbcTemplate.setQueryTimeout(60);
        
        return jdbcTemplate;
    }
    
    /**
     * Create the namedJdbcTemplate bean for the RMD database
     * @return NamedParameterJdbcTemplate
     */
    @Bean(value="assetNamedParameterJdbcTemplate")
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
        
        return new NamedParameterJdbcTemplate(jdbcTemplate());
    }
    
    /**
     * Create transaction manager
     * @param dataSource Datasource
     * @return transaction manager
     */
    @Bean(value="assetTransactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("assetDataSource") DataSource dataSource) {
        
        return new DataSourceTransactionManager(dataSource);
    }

Служебный компонент вызывается из кварца заданий в кластере. Служебный компонент определяется следующим образом:

/**
 * @author sgalgani
 *
 */
@Service("processSreService")
@Transactional("chainedTransactionManager")
public class ProcessSreServiceImpl implements ProcessSreService {

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

    @Autowired
    @Qualifier("historianService")
    private HistorianService historianService;

    @Autowired
    @Qualifier("sreEvolutionService")
    private SreEvolutionService sreEvolutionService;

    @Autowired
    @Qualifier("assetService")
    private AssetService assetService;

    @Autowired
    @Qualifier("configService")
    private ConfigService configService;

    @Autowired
    @Qualifier("engineSupportService")
    private EngineSupportService engineSupportService;

    @Autowired
    @Qualifier("tagAvailabilityService")
    private TagAvailabilityService tagAvailabilityService;

    @Autowired
    @Qualifier("engineTransformService")
    private EngineTransformService engineTransformService;

    @Autowired
    @Qualifier("quarantineService")
    private QuarantineService quarantineService;

    @Autowired
    @Qualifier("simpleRuleEventService")
    private SimpleRuleEventService simpleRuleEventService;

    @Value("${save.oracle.temporary.results}")
    private boolean saveOracleTemporaryResults;

    @Value("${enable.save.local.db.alerts}")
    private boolean enableSaveLocalDbAlerts;
    
    @Value("${simple.rule.event.service.enable}")
    private boolean simpleRuleEventServiceEnable;

    @SuppressWarnings("javadoc")
    @Override
    @Transactional(value = "chainedTransactionManager", rollbackFor = Exception.class, timeout = 120)
    public void processSre(Sre sre, List<TagLastTimestamp> tagsLastTimestamp, Metric metrics) throws Exception {

        LOGGER.info("[processSre] for JobId : {} and lineup: {} ",sre.getId(), sre.getLineupId() );

После аварийного переключения БД на Amazon RDS postgresql (потеря соединения с БД) я бы ожидал исключения тайм-аута транзакции через 120 секунд, но тайм-аут не работает, почему?


person Stefano    schedule 11.02.2021    source источник
comment
Пожалуйста, не размещайте код в виде изображений, так как это совершенно нечитаемо. Просто отправьте код как код.   -  person M. Deinum    schedule 11.02.2021
comment
хорошо, я редактирую часть изображения   -  person Stefano    schedule 11.02.2021
comment
Я думаю, что проблема, вызванная соединениями HikariCP, остается зависшей во время аварийного переключения в базе данных экземпляра AWS RDS PostgreSQL. Однако тайм-аут транзакции не работает. В этой статье описывается проблема с экземпляром AWS RDS и HikariCP theguardian. .com/info/2019/dec/02/. Я оставляю за собой право сделать тест, чтобы решить проблему и дать ответ.   -  person Stefano    schedule 12.02.2021


Ответы (1)


Я решил свою проблему с установкой свойства, как написано в следующей статье:

[https://www.theguardian.com/info/2019/dec/02/faster-postgresql-connection-recovery]

Мой код добавлен в конфигурацию HikariCP:

hikariConfig.addDataSourceProperty("socketTimeout", "120");

socketTimeout на 120 секунд, поэтому в любом случае свойство выдает следующее исключение по истечении времени ожидания:

Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) ~[?:?]    
at java.net.SocketInputStream.socketRead(SocketInputStream.java:115) ~[?:?]
at java.net.SocketInputStream.read(SocketInputStream.java:168) ~[?:?]   
at java.net.SocketInputStream.read(SocketInputStream.java:140) ~[?:?]  
at sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:448) ~[?:?]   
at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:68) ~[?:?]
at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1103) ~[?:?]
at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:823) ~[?:?]
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:161) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:128) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:113) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.PGStream.receiveChar(PGStream.java:370) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2015) ~[postgresql-42.2.10.jar!/:42.2.10]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:311) ~[postgresql-42.2.10.jar!/:42.2.10]... 17 more
person Stefano    schedule 18.02.2021