亲爱的, 我正在尝试做某种事件驱动的微服务。当前,当我使用Quarkus&Smallrye-Reactive消息传递扩展接收到消息时,我能够使用来自Kafka的消息并更新数据库记录。我想要进一步实现的是能够在成功的情况下将消息发送到其他主题,否则将消息发送到错误主题。我知道我们可以使用return和@outgoing批注来发出新消息,但我认为它不适合我的用例。如果在使用消息时发生错误,我在这里需要一个指导。我应该将消息返回到原始主题(通过不确认消息)还是应该使用它并向其他主题生成错误消息以回滚原始事务。
这是我的代码:
@Incoming("new-payment")
public void newMessage(String msg) {
LOG.info("New payment has been received.");
LOG.info("Payload is {}", msg);
PaymentEvent pe = jsob.fromJson(msg, PaymentEvent.class);
mysqlPool.preparedQuery("select totalBuyers from Book where isbn = ? ",
Tuple.of(pe.getIsbn()))
.thenApply(rs -> {
RowIterator<Row> iterator = rs.iterator();
if(iterator.hasNext()) {
return iterator.next().getInteger(0) + 1;
} else {
return Integer.valueOf(0);
}
})
.thenApply(totalCount -> {
return mysqlPool.preparedQuery("update Book set totalBuyers = ?",
Tuple.of(totalCount));
})
.whenComplete((rs, err) -> {
if(err != null) {
//Emit an error to error topic.
} else {
//Emit a msg to other service.
}
});
}
如果您有更好的代码,请提交,我仍然是反应式编程的新手:)。
答案 0 :(得分:1)
我从事企业集成已有多年了,我认为您会希望两者都做。
我应该将消息返回到原始主题(通过不确认) 消息)还是我应该使用它并产生错误消息以 不同的主题以回滚原始事务。
该事件应保留在主题上,以便其他实例有可能进行拾取和处理。并且错误消息应记录为事件。也许同一个消费者可以成功接听并重新处理事件。
EDA(事件驱动体系结构)可以提供不同的方式来处理此问题,但是在ESB上,消息将被标记为已尝试。通常,尝试了三次尝试会将其发送到死信队列,以便稍后可以对其进行纠正和重新处理。
我们的企业也开始使用EDA设计和构建应用程序,因此我很想阅读其他人在这个问题上要说的话。还有KUDOS,让您专注于Quarkus。我相信这是我所见过的Redhat最好的技术之一!
答案 1 :(得分:0)
此方法的另一个问题是,您正在执行“两次写入1服务”,例如一个呼叫数据库,另一个呼叫主题。当两次写入之一失败时,这可能会成为问题。
如果要避免这种情况,并使用纯事件驱动的方法,则需要对事件进行重新排序,以使写入db是整个流程中的最后一个事件,以便可以防止1写入2服务。
因此,在您的情况下:将第二个thenApply(..)方法从更新数据库更改为将新事件触发到另一个主题。这个新主题的使用者应该进行数据库更新。因此流程如下:
生产者->主题1->消费者(从...中选择),并将事件触发到另一个主题-> topic2->消费者(更新表)。