假设您有两个不同的微服务(Customer和Account),它们都作为Spring Boot应用程序在Docker容器中运行。每次创建新客户时,也应创建相应的帐户。为了编排这个流程,我有第三个“服务”来实现基于编排的传奇逻辑。
传奇“服务”包含以下代码。
@Saga
public class CustomerAccountSaga {
private static final String ACCOUNT_CREATION_DEADLINE = "sagas.account-creation-deadline";
private static final Logger LOGGER = LogManager.getLogger(CustomerAccountSaga.class);
@Autowired
private transient CommandGateway commandGateway;
@Autowired
private transient DeadlineManager deadlineManager;
private String customerId;
private String accountDeadlineId;
@StartSaga
@SagaEventHandler(associationProperty = "aggregateId")
private void on(CustomerCreatedEvent event) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("A new customer has been created for id = '{}'", event.getAggregateId());
}
this.customerId = event.getAggregateId().getId();
SagaLifecycle.associateWith("customerId", customerId);
//Both services has a CustomerId class defined in another package.
b.t.c.a.v.CustomerId id = new b.t.c.a.v.CustomerId(customerId);
CreateAccountCommand createAccount = new CreateAccountCommand(id);
commandGateway.send(createAccount);
this.accountDeadlineId = deadlineManager.schedule(Duration.ofDays(1), ACCOUNT_CREATION_DEADLINE);
}
@SagaEventHandler(associationProperty = "aggregateId")
private void on(CustomerDeletedEvent event) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("A customer with id '{}' has been deleted. "
+ "The customer was deleted before the account was created, "
+ "or the request to create the account timed-out",
event.getAggregateId());
}
deadlineManager.cancelSchedule(ACCOUNT_CREATION_DEADLINE, accountDeadlineId);
SagaLifecycle.end();
}
@SagaEventHandler(associationProperty = "customerId")
private void on(AccountCreatedEvent event) {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("A corresponding account for customer with id '{}' has been created",
event.getCustomerId());
}
deadlineManager.cancelSchedule(ACCOUNT_CREATION_DEADLINE, accountDeadlineId);
SagaLifecycle.end();
}
@DeadlineHandler(deadlineName = ACCOUNT_CREATION_DEADLINE)
public void on() {
if(LOGGER.isDebugEnabled()) {
LOGGER.debug("Failed to create a new account for customer with id '{}' in a timely fashion",
customerId);
}
//Both services has a CustomerId class defined in another package.
b.t.c.c.v.CustomerId id = new b.t.c.c.v.CustomerId(customerId);
DeleteCustomerCommand deleteCustomer = new DeleteCustomerCommand(id);
commandGateway.send(deleteCustomer);
}
}
当所有服务都启动并运行时,一切正常。CustomerCreatedEvent由saga处理程序处理,并按预期激发CreateCountCommand。后者导致创建帐户并触发AccountCreatedEvent,这也由saga逻辑处理。
当我尝试以下场景时,问题就出现了。在所有情况下,客户服务都在运行。
场景A
方案B
方案C
客户和帐户服务都已启动并运行。saga服务离线。
由于在所有情况下都不会发生预期行为,因此应用程序将处于不一致状态,因为不允许存在没有相应帐户的客户。
saga服务使用以下配置为Quartz和Axon为MySQL配置了一个持久存储。Axon对事件使用Jackson序列化器。
# Persistence configuration (MySQL)
###################################
# Quartz persistence
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=always
spring.quartz.properties.org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.dataSource=dsQuartz
spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_
spring.quartz.properties.org.quartz.dataSource.dsQuartz.user = ******
spring.quartz.properties.org.quartz.dataSource.dsQuartz.password = *******
spring.quartz.properties.org.quartz.dataSource.dsQuartz.maxConnections = 10
spring.quartz.properties.org.quartz.dataSource.dsQuartz.driver = com.mysql.cj.jdbc.Driver
spring.quartz.properties.org.quartz.dataSource.dsQuartz.URL = jdbc:mysql://192.168.99.100:3306/saga-store
# Axon persistence
spring.datasource.url=jdbc:mysql://192.168.99.100:3306/saga-store
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.username=******
spring.datasource.password=*****
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
问题:我是否误解了微服务和编配传奇的一些基本概念,或者我在设置/设计包含业务逻辑和编配传奇逻辑的不同微服务时忽略了什么?
谢谢你阅读我的帖子,并指出我错在哪里。
在不了解您的设置的情况下,我会说这一切都取决于配置。所以,基本上,当你启动一个@Saga
时,它在引擎盖下还有一个流式事件处理器
,它可以从尾部
(最旧的事件)或头部
(最新的事件)开始。
如ref指南所述,对于Saga流媒体处理器,默认为头。如果什么都没有配置,你的传奇故事只会对新的事件而不是过去的事件做出反应——你应该非常小心,在从一个事件切换到另一个事件之前好好考虑一下。
另一个需要注意的要点是关于Saga Store
,如果没有配置任何内容,它会使用InMemorySagaStore
。当然,这可能不理想,您会配置一个持久的。我们的参考指南再次提供了所有的部分。
服务调用失败 KernalEvent::SERVICE_FAIL事件 在框架层,调用servcie时,会抛出KernalEvent::SERVICE_FAIL事件,你可以监听该事件,做数据上报处理,请以异步方式上报 配置config/lister.php中的事件监听器 示例 <?php namespace src\Web\Listeners; class ServiceFailListener e
我们不断收到此错误: 我们已经验证了activemq作为activemq运行,我们已经验证了目录的所有者是activemq。它不会自动创建目录,如果我们自己创建,它仍然会给出同样的错误。服务开始很好,但是它会不断地抛出同样的错误。没有锁定文件,因为它不会生成任何文件或目录。
有人知道为什么。
问题内容: 我正在创建应用程序并在其中使用一些hibernate的东西。我要做的就是将实体保存到数据库中,但我不断收到此异常: 起初,我遇到了这个异常: 然后,我发现需要将其添加到我的hibernate配置中: 这解决了这个问题,但是现在出现了上面的问题。我将实体保存到这样的数据库中: 我的hibernate.cfg.xml文件如下所示: 我在用: Hibernate-4.1.4.Final JD
末流985,投了好多家游策都没啥反应,只有剑心和西山居无论实习还是春招都是给面子次次进(爱您,虽然前两次全部折戟,这一次还是笔试挂了被捞,大概是因为没实习+项目经验,但是有mmo经验保底) 作品集:MMO关卡拆解、MMO拆解、世界观设定、人物小传、UE4Demo、系统反策划案 目前拿了家小厂offer,就业困难没人要!在面剑心,想回馈一下牛客,所以就记下来啦! 2022.10.19 西山居 实习面
当我录制这个命令以显示mongodb的状态时