Akka.DependencyInjection 无法解决依赖项时不会抛出错误

Akka.DependencyInjection doesn't throw error when can't resolve dependencies

我按以下方式使用 DI:

 _actorSystem.ActorOf(
    Supervise(PropsWithDI<MessagePublisherActor>()), MessagePublisher.ActorName);

private Props PropsWithDI<T>(params object[] args) where T : ActorBase
    => DependencyResolver.For(_actorSystem).Props<T>(args);

如果以某种方式存在未添加到 DI 容器的构造函数参数,它根本不会创建 Actor,这当然是正常的,但我预计会出现错误或其他问题。

我是不是用错了,或者这是 Akka.NET Akka.DependencyInjection.

缺少的功能

查看代码后,我发现这实际上是一种设计选择。

ActorSystem 在设计时考虑了故障隔离,它的设计使得在单个 actor 级别发生的任何故障都不会传播到应用程序层并使应用程序崩溃,就像在任何操作系统中一样,你不'希望单个进程中的错误导致整个操作系统崩溃。

为实现这一点,参与者在自己的气泡内异步启动,以创建高度的故障隔离。它实际上分两步完成:

  1. ActorOf() 方法返回一个空的 actor holder,这个 holder 包含 MailBoxActorCellActorCell 包含系统需要的道具 re/create actor 根据需要。
  2. Create 条系统消息被排入邮箱,触发实际的 Actor 实例化。

这本质上是参与者代码所在的“气泡”,任何代码在第 2 步之后抛出的任何异常都被阻止传播到应用层,而是向上传播到它上面的参与者链,让他们决定关于过失行为者会发生什么。由于 DI 异常发生在流程的第 2 步,异常永远不会到达实际调用 ActorOf() 方法的代码,而是传播到监护人角色并在日志中记录为错误。

看起来你至少可以在运行时捕获错误,这很有帮助。 我最终得到了类似的结果:

.WithSupervisorStrategy(new OneForOneStrategy(receivedException =>
                {
                    _logger.LogError("Eror: {exception}", receivedException);
                    return Directive.Escalate;
                }));

这篇文章有更多关于如何设置主管的信息:

https://getakka.net/articles/concepts/supervision.html

var childProps = Props.Create<EchoActor>();

var supervisor = BackoffSupervisor.Props(
    Backoff.OnStop(
        childProps,
        childName: "myEcho",
        minBackoff: TimeSpan.FromSeconds(3),
        maxBackoff: TimeSpan.FromSeconds(30),
        randomFactor: 0.2)
        .WithAutoReset(TimeSpan.FromSeconds(10))
        .WithSupervisorStrategy(new OneForOneStrategy(exception =>
        {
            if (exception is MyException)
                return Directive.Restart;
            return Directive.Escalate;
        })));

system.ActorOf(supervisor, "echoSupervisor");