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 级别发生的任何故障都不会传播到应用程序层并使应用程序崩溃,就像在任何操作系统中一样,你不'希望单个进程中的错误导致整个操作系统崩溃。
为实现这一点,参与者在自己的气泡内异步启动,以创建高度的故障隔离。它实际上分两步完成:
ActorOf()
方法返回一个空的 actor holder,这个 holder 包含 MailBox
和 ActorCell
。 ActorCell
包含系统需要的道具 re/create actor 根据需要。
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");
我按以下方式使用 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 级别发生的任何故障都不会传播到应用程序层并使应用程序崩溃,就像在任何操作系统中一样,你不'希望单个进程中的错误导致整个操作系统崩溃。
为实现这一点,参与者在自己的气泡内异步启动,以创建高度的故障隔离。它实际上分两步完成:
ActorOf()
方法返回一个空的 actor holder,这个 holder 包含MailBox
和ActorCell
。ActorCell
包含系统需要的道具 re/create actor 根据需要。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");