4、Akka容错处理

监督(Supervision)

容错(fault tolerance)概念与 Actor 相关,Actor 模型中容错处理使用叫做监督(supervision)处理。监督的核心思想就是把对于失败的响应和可能引起失败的组件分隔开,并且把可能发生错误的组件通过层级结构来组织,以便管理。

在分布式系统中每个组件都是一个定时炸弹,那么我们希望能够确保无论其中任何一个发生爆炸,都不会引发链式反应,导致其他组件也爆炸。也可以说,我们希望能够隔离错误,或是将可能引发失败情况的组件分离开来。

监督的层级结构

Akka 使用 Actor 层级结构来描述监督。当我们创建 Actor 时,新建的 Actor 都是作为另一个 Actor 的子 Actor,父 Actor 负责监督子 Actor。Actor 的路径结构就展示了它的层级结构,所以和文件系统中的文件夹有点像。
在这里插入图片描述

监督策略

在Akka框架内,父Actor对子Actor进行监督,监控子Actor的行为是否有异常。大体上,监控策略分为两种:

  1. OneForOneStrategy策略:父Actor只会对出问题的子Actor进行处理。比如重启或停止。Akka的默认策略,推荐使用。
  2. AllForOneStrategy策略:父Actor会对出问题的子Actor以及它所有的兄弟节点都进行处理。只适用于各个Actor联系非常紧密的场景,如果多个Actor只要有一个失败,则宣布整个任务失败的情况。

Actor中具体的处理方式主要包括以下:

  • 继续(resume) :Actor 继续处理下一条消息;
  • 停止(stop) :停 止 Actor,不再做任何操作;
  • 重启(restart) :新建一个 Actor,代替原来的 Actor;
  • 向上反映(escalate) :将异常信息传递给下一个监督者。

创建监督策略

public class JavaSupervisorStrategyDemo extends AbstractActor {
    private static SupervisorStrategy strategy =
            new OneForOneStrategy(
                    10,
                    Duration.create("1 minute"),
                    /*
                     * resume(): Actor 继续处理下一条消息;
                     * restart():  停 止Actor,不再做任何操作;
                     * escalate(): 新建一个 Actor,代替原来的 Actor;
                     * stop(): 将异常信息传递给下一个监督者;
                     */
                    DeciderBuilder.match(ArithmeticException.class, e -> SupervisorStrategy.resume())
                            .match(NullPointerException.class, e -> SupervisorStrategy.restart())
                            .match(IllegalArgumentException.class, e -> SupervisorStrategy.stop())
                            .matchAny(o -> SupervisorStrategy.escalate())
                            .build());

    @Override
    public SupervisorStrategy supervisorStrategy() {
        return strategy;
    }
}

一对一策略(one-for-one strategy)意味着每个子级都被单独对待。在上面的示例中,10Duration.create(1, TimeUnit.MINUTES)分别传递给maxNrOfRetrieswithinTimeRange参数,这意味着策略每分钟重新启动一个子级最多10次。如果在withinTimeRange持续时间内重新启动计数超过maxNrOfRetries,则子 Actor 将停止。

如果策略在监督者 Actor(而不是单独的类)中声明,则其决策者可以线程安全方式访问 Actor 的所有内部状态,包括获取对当前失败的子级的引用,可用作失败消息的getSender()

默认监督策略

一般情况下使用默认的行为就可以了:如果 Actor 在运行中抛出异常,就重启 Actor;如果发生错误,就向上反映或是关闭应用程序。不过如果 Actor 在构造函数中抛出异常,那么会导致 ActorInitializationException,并最终导致 Actor 停止运行。

如果没有为 Actor 定义监督策略,则默认情况下会处理以下异常:

  • ActorInitializationException将停止失败的子 Actor
  • ActorKilledException将停止失败的子 Actor
  • DeathPactException将停止失败的子 Actor
  • Exception将重新启动失败的子 Actor
  • 其他类型的Throwable将向上反映到父级 Actor

如果异常一直升级到根守护者,它将以与上面定义的默认策略相同的方式处理它。

停止监督策略

在子级失败时采取措施阻止他们,然后在DeathWatch显示子级死亡时由监督者采取纠正措施。此策略还预打包为SupervisorStrategy.stoppingStrategy,并附带一个StoppingSupervisorStrategy配置程序,以便在您希望/user下监护人应用它时使用。

记录 Actor 的失败

默认情况下,除非向上反映escalate,否则SupervisorStrategy会记录故障。escalate的故障应该在层次结构中更高的级别处理并记录下来。

通过在实例化时将loggingEnabled设置为false,可以将SupervisorStrategy的默认日志设置为静音。定制的日志记录可以在Decider内完成。

请注意,当在监督者 Actor 内部声明SupervisorStrategy时,对当前失败的子级的引用可用作sender

你还可以通过重写logFailure方法自定义自己的SupervisorStrategy中的日志记录。

参考文献

《Akka入门与实践》 – 第三章 传递消息

回复Akka领取《Akka入门与实践》书籍

关注公众号 ,专注于java大数据领域离线、实时技术干货定期分享!回复Akka领取《Akka入门与实践》书籍,个人网站 www.lllpan.top

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值