【问题标题】:AKKA.NET question: Is it a good idea to have more than one ActorSystem in an application?AKKA.NET 问题:在应用程序中拥有多个 ActorSystem 是个好主意吗?
【发布时间】:2019-07-11 09:41:13
【问题描述】:

我正在为 C# 桌面应用程序(不是服务器,而是桌面 GUI 应用程序)编写插件。 为了使我们的线程问题更简单,我正在研究是否可以在这些插件中使用 AKKA.NET。 这些插件主要是相互独立的。 因此,从架构 POV 来看,给每个插件它自己的“私有”ActorSystem 实例是很自然的。 这种方法的优点是插件最大限度地相互隔离。 另一方面,我阅读了一些关于 Akka for JVM 的文章,这些文章告诉我,在应用程序中拥有太多 ActorSystem 实例是一种反模式,因为 ActorSystem 非常重量级。

并发插件的实际数量是 10 到 20 个,即应用程序内部最多可以运行 20 个 ActorSystem 实例。同样,这是一个 GUI 桌面应用程序,通常在终端服务器会话中运行(即,可能有许多这些 GUI 应用程序在终端服务器上运行)。

那么 - 这种简单的方法(每个库一个 ActorSystem)是否可行?还是设计一种使用全局 ActorSystem 的方法更好,它使用每个插件的顶级参与者来隔离插件。 这种方法可能对性能更好,但我有点担心,因为插件之间没有那么隔离。

那么 - 这种“多系统”方法是一种好的架构方法,还是坚持“一个全局系统”设计更好?您在这里有什么经验?

【问题讨论】:

  • 在我看来,您想太多问题了。我不明白 AKKA.NET 如何适合插件。
  • 我们正在考虑的插件都有多个线程触发事件。我们在这里考虑 akka 的基本原因是,我们对简单线程处理的替代方案看起来像是我们自己实现了一个最小的 Actor 系统。 TL;DR:我们在这里使用 AKKA 的原因是为了简化我们的插件的线程问题,而不必自己编写一个 Actor 系统。
  • 好吧,另一个问题,为什么插件有多个线程?与 tasks/async/await 一起使用会更好吗?
  • async/await 在某些地方使用,但对于我们的目标插件来说它不是那么有用,因为这些代码部分只是处理各种事件源,其中事件来自多个线程.

标签: c# akka.net


【解决方案1】:

那么 - 这种简单的方法(每个库一个 ActorSystem)是否可行?还是设计一种使用全局 ActorSystem 的方法更好,它使用每个插件的顶级参与者来隔离插件。这种方法可能对性能更好,但我有点担心,因为插件之间没有那么隔离。

这是我将采用的方法 - 让每个插件使用相同的 ActorSystem 创建自己的演员层次结构。每个插件都可以有自己的演员和消息类型,没有重叠。如果你最终运行了多个ActorSystems,你最终仍然会有多个actor都使用相同的线程,因为默认情况下ActorSystem将actor调度到TPL和桌面其他部分的同一个.NET线程池中应用程序可能会使用。让一个 ActorSystem 管理所有这些可能是最简单的,因为这样你就有一个调度程序在同一组线程上编组执行(竞争较少。)

【讨论】:

    【解决方案2】:

    如果隔离是您的目标,那么多个参与者系统将无法解决您的问题 - ActorSystem 只是一个普通类,您仍然可以使用静态字段共享数据,并且(可能)您仍然可以访问其他参与者系统,如果你有足够的决心。因此,如果您运行不受信任的代码,actor 系统将无法帮助您。

    .NET 中真正的进程内隔离可以通过在旧的 .NET Framework 中使用 AppDomains 或在 .NET Core 中使用 AssemblyLoadContext 来实现。

    请记住,使用 Actor 编程范式是一项严肃的设计决策,并且可以通过多种方式实现组件隔离。因此,如果组件隔离是您决定使用 Actor 的唯一原因,您可能需要注意并重新考虑其他选项。

    Akka.NET 扩展

    您可以为每个插件使用actor,甚至可以使用本机Akka.NET 扩展——这是允许我们为akka 本身构建插件的机制。几乎所有 Akka 更高级别的特性都是作为扩展构建的:集群、远程处理、集群分片、持久性等。

    要构建一个扩展,你需要两个类:

    public class MyExtensionProvider : ExtensionIdProvider<MyExtension>
    {
        public override MyExtension CreateExtension(ExtendedActorSystem system) =>
            new MyExtension(system);
    }
    
    public class MyExtension : IExtension
    {
        public MyExtension(ExtendedActorSystem system) { }
    }
    

    您可以通过以下方式从代码本身注册和检索这些扩展:actorSystem.WithExtension&lt;MyExtension, MyExtensionProvider&gt;()(也可以覆盖该方法的检出)。您也可以直接在 HOCON 中注册它们 - 这样当通过 HOCON config 提供时,它们将在系统启动时自动启动:

    akka.extensions = [
        "MyNamespace.MyExtensionProvider1, MyAssembly",    
        "MyNamespace.MyExtensionProvider2, MyAssembly"
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      • 2019-10-19
      • 2018-06-27
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多