【问题标题】:Akka and Backup/Fallback ActorsAkka 和备份/后备演员
【发布时间】:2025-12-07 07:20:03
【问题描述】:

Hystrix-land 待了很长时间后,我来到了 Akka,在这里,和 Akka 一样,失败是一等公民。

在 Hystrix 中,我可能有一个 SaveFizzToDbCmd 尝试将 Fizz 实例保存到 RDB(MySQL 等),以及一个备份/“fallbackSaveFizzToMemoryCmd 保存Fizz 到内存缓存中,以防主(DB)命令出现故障/开始失败:

// Groovy pseudo-code
class SaveFizzToDbCmd extends HystrixCommand<Fizz> {
    SaveFizzToMemoryCmd memoryFallback
    Fizz fizz

    @Override
    Fizz run() {
        // Use raw JDBC to save ‘fizz’ to an RDB.
    }

    @Override
    Fizz getFallback() {
        // This only executes if the ‘run()’ method above throws
        // an exception.
        memoryFallback.fizz = this.fizz
        memoryFallback.execute()
    }
}

在 Hystrix 中,如果run() 抛出异常(比如SqlException),则调用其getFallback() 方法。如果在一定时间内抛出足够多的异常,HystrixCommands“断路器”就会“跳闸”,只会调用getFallback()方法。

我有兴趣在 Akka 中完成同样的任务,但要使用演员。使用 Akka,我们可能有一个 JdbcPersistor 演员和一个 InMemoryPersistor 备份/后备演员,如下所示:

class JdbcPersistor extends UntypedActor {
    @Override
    void onReceive(Object message) {
        if(message instanceof SaveFizz) {
            SaveFizz saveFizz = message as SaveFizz
            Fizz fizz = saveFizz.fizz

            // Use raw JDBC to save ‘fizz’ to an RDB.
        }
    }
}

class InMemoryPersistor extends UntypedActor {
    // Should be obvious what this does.
}

我正在努力解决的问题是:

  • InMemoryPeristor 失败时,如何将InMemoryPeristor 正确配置/连接为JdbcPersistor 的备份;和
  • 如果/当它“治愈”(尽管它可能永远不会)时,故障切换回 JdbcPersistor

我会想象这是属于 JdbcPersistors SupervisorStrategy 内部的逻辑,但我在 Akka 文档中找不到任何东西,也找不到任何实现这种行为的代码 sn-ps。这告诉我“嘿,也许这不是 Akka 的工作方式,也许在 Akka-land 中进行这种断路/故障转移/故障恢复的方式不同。”想法? p>

请注意:Java 示例非常受到赞赏,因为 Scala 在我看来就像象形文字!

【问题讨论】:

    标签: java akka hystrix fault-tolerance akka-supervision


    【解决方案1】:

    一种方法是让消费代码与之通信的 FailoverPersistor 演员,它有一个 JdbcPersistor 和一个 InMemoryPeristor 作为孩子和一个标志,决定使用哪一个,然后基本上将流量路由到正确的孩子取决于状态。然后,该标志可以由主管和参与者内部的定时逻辑/统计信息进行操作。

    akka 的 contrib 包中有一个断路器,它可能是一个灵感(或者甚至可以用来实现你想要的):http://doc.akka.io/docs/akka/current/common/circuitbreaker.html

    【讨论】: