如何正确使用quarkus和smallrye做事件驱动的微服务

时间:2019-12-26 06:28:28

标签: quarkus smallrye-reactive-messaging

亲爱的, 我正在尝试做某种事件驱动的微服务。当前,当我使用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.
                }
            });
    }

如果您有更好的代码,请提交,我仍然是反应式编程的新手:)。

2 个答案:

答案 0 :(得分:1)

我从事企业集成已有多年了,我认为您会希望两者都做。

我应该将消息返回到原始主题(通过不确认) 消息)还是我应该使用它并产生错误消息以 不同的主题以回滚原始事务。

该事件应保留在主题上,以便其他实例有可能进行拾取和处理。并且错误消息应记录为事件。也许同一个消费者可以成功接听并重新处理事件。

EDA(事件驱动体系结构)可以提供不同的方式来处理此问题,但是在ESB上,消息将被标记为已尝试。通常,尝试了三次尝试会将其发送到死信队列,以便稍后可以对其进行纠正和重新处理。

我们的企业也开始使用EDA设计和构建应用程序,因此我很想阅读其他人在这个问题上要说的话。还有KUDOS,让您专注于Quarkus。我相信这是我所见过的Redhat最好的技术之一!

答案 1 :(得分:0)

此方法的另一个问题是,您正在执行“两次写入1服务”,例如一个呼叫数据库,另一个呼叫主题。当两次写入之一失败时,这可能会成为问题。

如果要避免这种情况,并使用纯事件驱动的方法,则需要对事件进行重新排序,以使写入db是整个流程中的最后一个事件,以便可以防止1写入2服务。

因此,在您的情况下:将第二个thenApply(..)方法从更新数据库更改为将新事件触发到另一个主题。这个新主题的使用者应该进行数据库更新。因此流程如下:

生产者->主题1->消费者(从...中选择),并将事件触发到另一个主题-> topic2->消费者(更新表)。