【发布时间】:2020-05-18 13:27:28
【问题描述】:
我使用 mysql 作为事件存储,因此 axon-server-connector 被排除在类路径之外。我的用例描述如下。
- Spring Boot 2.1.7.RELEASE 和 axon 4.3.2
- 我打算有三个数据库,分别用于轴突事件存储、投影写入和投影读取。
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean("axonMaster")
@ConfigurationProperties("spring.datasource.hikari.axon-master")
public DataSource axon() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean("projectionRead")
@ConfigurationProperties("spring.datasource.hikari.projection-write")
public DataSource master() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean("projectionWrite")
@ConfigurationProperties("spring.datasource.hikari.projection-read")
public DataSource slave() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
}
- 我尝试使用 spring data jpa 配置多个数据源。主要的如下所示。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "axonEntityManagerFactory",
basePackages = "org.axonframework.eventsourcing.eventstore.jpa") // (1)
public class AxonEventStoreConfig {
@Primary
@Bean(name="axonEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, @Qualifier("axonMaster") DataSource axonMaster) {
return builder
.dataSource(axonMaster)
.packages("org.axonframework.eventsourcing.eventstore.jpa")
.persistenceUnit("axonMaster") //(2)
.build();
}
@Primary
@Bean(name = "axonPlatformTransactionManager") //(3)
public PlatformTransactionManager transactionManager(
@Qualifier("axonEntityManagerFactory") EntityManagerFactory axonEntityManagerFactory) {
return new JpaTransactionManager(axonEntityManagerFactory);
}
}
关于这部分的问题是:
(1)将basePackages设置为org.axonframework.eventsourcing.eventstore.jpa就够了吗?也许我还需要添加令牌包 org.axonframework.eventhandling.tokenstore.jpa 和 soga 包?我将使用 soga 商店。
(2) 这里的包和上一个包是一样的吗? persistenceUnit 的名称应该是什么?
示例项目上传到github:https://github.com/sincosmos/axon-multiple-databases
我无法运行应用程序。
我做的一切都正确吗?我参考了https://github.com/AxonIQ/giftcard-demo的例子,但是多数据库版本是基于axon 2.0,也需要配置axon command bus。
目标似乎很简单,在 axon 框架应用程序中配置多个数据库(一个用于事件存储),但即使我花了几天时间,我仍然一无所获。
谁能给我一些建议或帮助?我将不胜感激。
/****************************更新20200521 **************** ************/
我在阅读 Allard 的答案后取得了进步,现在我可以为应用程序配置多个数据库。源码上传到githubhttps://github.com/sincosmos/axon-multiple-databases.git
特别是对于axon event store,db配置如下图所示。
@Configuration
@EnableTransactionManagement
public class AxonEventStoreConfig {
@Bean("axonMaster")
@ConfigurationProperties("spring.datasource.hikari.axon-master")
public DataSource axon() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name="axonEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, @Qualifier("axonMaster") DataSource axonMaster) {
return builder
.dataSource(axonMaster)
.persistenceUnit("axonMaster")
.properties(jpaProperties())
.packages("org.axonframework.eventhandling.tokenstore",
"org.axonframework.modelling.saga.repository.jpa",
"org.axonframework.eventsourcing.eventstore.jpa")
.build();
}
/**
* Is it right to provide EntityManagerProvider like this ???
* For axon event store
* @param entityManagerFactory
* @return
*/
@Bean
public EntityManagerProvider entityManagerProvider(@Qualifier("axonEntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return () -> entityManagerFactory.getObject().createEntityManager();
}
private Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
props.put("hibernate.hbm2ddl.auto", "update");
props.put("hibernate.show_sql", "true");
return props;
}
}
在我启动应用程序后(如果是第一次,将自动创建事件存储相关表),轴突的数据库连接池很快就会耗尽。日志已粘贴供您参考。
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
Hibernate: select min(domaineven0_.global_index)-1 as col_0_0_ from domain_event_entry domaineven0_
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
19:59:57.223 [EventProcessor[com.baeldung.axon.querymodel]-0] WARN o.a.e.TrackingEventProcessor - Fetch Segments for Processor 'com.baeldung.axon.querymodel' failed: no transaction is in progress. Preparing for retry in 1s
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
Hibernate: select min(domaineven0_.global_index)-1 as col_0_0_ from domain_event_entry domaineven0_
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
19:59:58.293 [EventProcessor[com.baeldung.axon.querymodel]-0] WARN o.a.e.TrackingEventProcessor - Fetch Segments for Processor 'com.baeldung.axon.querymodel' failed: no transaction is in progress. Preparing for retry in 2s
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
Hibernate: select min(domaineven0_.global_index)-1 as col_0_0_ from domain_event_entry domaineven0_
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
20:00:00.361 [EventProcessor[com.baeldung.axon.querymodel]-0] WARN o.a.e.TrackingEventProcessor - Fetch Segments for Processor 'com.baeldung.axon.querymodel' failed: no transaction is in progress. Preparing for retry in 4s
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
Hibernate: select min(domaineven0_.global_index)-1 as col_0_0_ from domain_event_entry domaineven0_
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
20:00:04.465 [EventProcessor[com.baeldung.axon.querymodel]-0] WARN o.a.e.TrackingEventProcessor - Fetch Segments for Processor 'com.baeldung.axon.querymodel' failed: no transaction is in progress. Preparing for retry in 8s
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
Hibernate: select min(domaineven0_.global_index)-1 as col_0_0_ from domain_event_entry domaineven0_
Hibernate: select tokenentry0_.segment as col_0_0_ from token_entry tokenentry0_ where tokenentry0_.processor_name=? order by tokenentry0_.segment ASC
20:00:12.531 [EventProcessor[com.baeldung.axon.querymodel]-0] WARN o.a.e.TrackingEventProcessor - Fetch Segments for Processor 'com.baeldung.axon.querymodel' failed: no transaction is in progress. Preparing for retry in 16s
20:00:17.327 [HikariPool-1 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Pool stats (total=15, active=15, idle=0, waiting=0)
20:00:22.178 [HikariPool-2 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-2 - Pool stats (total=10, active=0, idle=10, waiting=0)
20:00:23.092 [HikariPool-3 housekeeper] DEBUG com.zaxxer.hikari.pool.HikariPool - HikariPool-3 - Pool stats (total=10, active=0, idle=10, waiting=0)
当我在 mysql 工作台中检查连接状态时,这些连接的状态为“睡眠”。更改连接池大小没有帮助。我还检查了jvm的堆栈,没有发现死锁。我将数据源泄漏检测阈值设置为 10000,但您可以看到没有打印数据源泄漏信息。 你能帮忙吗?
/****************************更新20200522 **************** ************/
事实证明“javax.persistence.TransactionRequiredException:没有事务正在进行中”是在事件处理器尝试访问 mysql 事件存储时发生的。我为每个数据源配置了事务管理器,但错误仍然存在。不知道发生了什么...
【问题讨论】:
-
如果您的设置中有
org.axonframework.common.transaction.TransactionManagerbean,可能值得验证。当您使用 spring 时,采用SpringTransactionManager(包装 Spring 的PlatformTransactionManager)将是最佳选择。这一切都应该是自动配置的,但是当您遇到事务问题时...... -
谢谢史蒂文。我决定先开发业务逻辑。如果我以后能解决问题,我会更新帖子。
-
这完全有道理@sincosmos。希望它会在这个过程中得到解决,如果没有,我们会在适当的时候注意到问题更新。祝你好运!
标签: spring-data-jpa event-sourcing axon