我使用 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.eventcommerce.eventstore.jpa就足够了吗?也许我还需要添加令牌包 org.axonframework.eventhandling.tokenstore.jpa 和 soga 包?我会使用soga商店。
(2) 这里的套餐和之前的一样吗? persistenceUnit 的名称应该是什么?
示例项目上传到github:https://github.com/sincosmos/axon-multiple-databases https://github.com/sincosmos/axon-multiple-databases
我无法运行该应用程序。
我做的一切都正确吗?我参考了这个例子https://github.com/AxonIQ/giftcard-demo https://github.com/AxonIQ/giftcard-demo,但多数据库版本是基于axon 2.0,还需要配置axon命令总线。
目标看起来很简单,在 axon 框架应用程序中配置多个数据库(一个用于事件存储),但即使我花了几天时间,我仍然一无所获。
有人可以给我一些建议或帮助吗?我将非常感激。
/**************************** 更新 20200521 ****************** *********/
阅读 Allard 的答案后我取得了进展,现在我可以为应用程序配置多个数据库。源码已上传至githubhttps://github.com/sincosmos/axon-multiple-databases.git https://github.com/sincosmos/axon-multiple-databases.git
特别是,对于 axon 事件存储,数据库配置如下所示。
@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;
}
}
启动应用程序后(如果是第一次,将自动创建事件存储相关表),axon 的数据库连接池很快就会耗尽。日志贴出来供大家参考。
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 ****************** *********/
事实证明,当事件处理器尝试访问 mysql 事件存储时,发生了“javax.persistence.TransactionRequiredException:没有事务正在进行”。我为每个数据源配置了事务管理器,但错误仍然存在。不知道发生了什么......