Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有持久邮箱的Akka无状态参与者_Akka_Actor_Akka Cluster_Akka Persistence - Fatal编程技术网

具有持久邮箱的Akka无状态参与者

具有持久邮箱的Akka无状态参与者,akka,actor,akka-cluster,akka-persistence,Akka,Actor,Akka Cluster,Akka Persistence,我想创建一个拥有1000名演员的阿克卡集群。每个参与者都会收到一条消息,进行一些计算,并将结果写入一个专用的卡夫卡主题 它应该部署在集群中,例如Kubernetes 我的理解是,如果参与者被终止(JVM崩溃、重新部署或其他原因),那么其邮箱的内容以及当前正在处理的消息都将丢失 这在我的例子中是完全不可接受的,因此我想实现一种拥有持久邮箱的方法。请注意,参与者本身是无状态的,他们不需要重播消息或重建状态。如果演员被终止,我所需要的就是不要丢失消息 问题是:推荐的方法是什么?他们建议实现持久参与者。

我想创建一个拥有1000名演员的阿克卡集群。每个参与者都会收到一条消息,进行一些计算,并将结果写入一个专用的卡夫卡主题

它应该部署在集群中,例如Kubernetes

我的理解是,如果参与者被终止(JVM崩溃、重新部署或其他原因),那么其邮箱的内容以及当前正在处理的消息都将丢失

这在我的例子中是完全不可接受的,因此我想实现一种拥有持久邮箱的方法。请注意,参与者本身是无状态的,他们不需要重播消息或重建状态。如果演员被终止,我所需要的就是不要丢失消息

问题是:推荐的方法是什么?他们建议实现持久参与者。但就像我说的,我不需要坚持和恢复演员的任何状态。我应该实现一个基于持久存储(如SQL数据库)的自定义邮箱吗


我还看到,在某些版本之前,Akka支持“持久”邮箱,这似乎是我所需要的。但出于某种原因,他们删除了它,这让人困惑…

你可以用卡夫卡来实现你想要的。卡夫卡主题是持久性的(如果您在卡夫卡中将保留设置为“永远”,或者对主题启用日志压缩,那么数据将“一直”保留,或者您可以在卡夫卡之外存储偏移量)

使用Akka Streams,您将在广播您制作的消息(制作主题)后提交您收到的消息(关于接收主题),从而提供“至少一次”传递语义。(对于“恰好一次”,您可以查看Kafka事务)

这是《阿尔帕卡·卡夫卡文件》中的示例:

Consumer.DrainingControl<Done> control =
    Consumer.committableSource(consumerSettings, Subscriptions.topics(topic))
        .map(
            msg ->
                ProducerMessage.single(
                    new ProducerRecord<>(targetTopic, msg.record().key(), msg.record().value()),
                    msg.committableOffset() // the passThrough
                    ))
        .via(Producer.flexiFlow(producerSettings))
        .map(m -> m.passThrough())
        .toMat(Committer.sink(committerSettings), Keep.both())
        .mapMaterializedValue(Consumer::createDrainingControl)
        .run(materializer);

如果您有多个参与者可以同时处理消息,那么您还可以增加
mapsync
调用的并行系数。

在客户端上使用持久参与者是此类需求的建议。我理解您是说您的接收参与者不需要持久性/sta但是,通过在客户端上使用持久性,您可以在接收参与者终止时重试,也可以使用开箱即用的保证消息传递功能来确保已对其进行处理。本质上,持久性用于(在客户端)持久化所做的请求,以便客户端可以将消息重新发送到“如有必要,重新生成邮箱

使用客户端持久性是:

  • 比持久邮箱性能更好
  • 针对更多故障场景(如网络层丢弃的消息、应用程序逻辑中的故障)提供保护
  • 更灵活,支持更多类型的恢复(例如:仅需要恢复某些消息的场景)
这就是为什么从Akka中删除了持久邮箱:Akka持久性/保证至少一次交付从本质上说是一个比持久邮箱更好的解决方案

stikkos使用卡夫卡的答案也是可行的。我只是担心卡夫卡的引入会增加很多复杂性。当然,任何持久性存储都会增加复杂性,所以我想这取决于你已经准备好了什么

Consumer.DrainingControl<Done> control =
    Consumer.committableSource(consumerSettings, Subscriptions.topics(topic))
            .mapAsync(1, msg -> 
                Patterns.ask(actor, msg, Duration.ofSeconds(5))
                    .thenApply(done ->
                        ProducerMessage.single(
                                new ProducerRecord<>(targetTopic, done.key(), done.value()),
                                msg.committableOffset() // the passThrough
                        )
                    )
            )
            .via(Producer.flexiFlow(producerSettings))
            .map(m -> m.passThrough())
            .toMat(Committer.sink(committerSettings), Keep.both())
            .mapMaterializedValue(Consumer::createDrainingControl)
            .run(materializer);