我正在为C#桌面应用程序(不是服务器,而是桌面图形用户界面应用程序)编写插件。为了使我们的线程问题更简单,我正在研究是否可以在这些插件中使用AKKA.NET。插件基本上是彼此独立的。因此,从架构观点来看,给每个插件提供它自己的“私有”ActorSystem实例是很自然的。这种方法的优点是插件之间最大限度地相互隔离。另一方面,我读过一些关于Akka for the JVM的文章,这些文章告诉我,在应用程序中拥有太多的ActorSystem实例是一种反模式,因为ActorSystem是相当重量级的。
并发插件的实际数量是10- 20,也就是说,应用程序在最坏的情况下可能有20个ActorSystem实例在其中运行。同样,这是一个GUI桌面应用程序,它通常在终端服务器会话中运行(即,可能有许多这样的GUI应用程序在终端服务器上运行)。
那么-这种简单化的方法(每个库一个ActorSystem )是可行的吗?或者更好的方法是设计一种使用全局ActorSystem的方法,它使用每个插件的顶级角色来隔离插件。这种方法可能对性能更好,但我有点担心它,因为插件不是彼此隔离的。
那么,这种“多系统”方法是一种好的架构方法,还是坚持“一个全球系统”的设计更好呢?你在这里的经历是什么?
发布于 2019-07-12 15:43:06
So -这种简单化的方法(每个库一个ActorSystem )是可行的吗?或者更好的方法是设计一种使用全局ActorSystem的方法,它使用每个插件的顶级角色来隔离插件。这种方法可能对性能更好,但我有点担心它,因为插件不是彼此隔离的。
这是我采用的方法-让每个插件使用相同的ActorSystem创建自己的角色层次结构。每个插件都可以有自己的参与者和消息类型,没有重叠。如果您最终运行多个ActorSystem,您最终仍然会拥有多个都使用相同线程的actors,因为默认情况下,ActorSystem会将actors调度到.NET和桌面应用程序的其他部分可能使用的同一个TPL线程池中。让一个ActorSystem管理所有这些可能是最简单的,因为这样您就有了一个分派器,在同一组线程上编组执行(竞争较少)。
发布于 2019-07-12 13:20:32
如果你的目标是隔离,那么多个参与者系统不会解决你的问题-- ActorSystem只是一个普通的类,你仍然可以使用静态字段来共享数据,并且(很可能)如果你有足够的决心,你仍然可以访问其他的参与者系统。因此,如果您运行不受信任的代码,actor系统将不会对您有所帮助。
.NET中真正的进程内隔离可以通过使用旧.NET框架中的AppDomains或.NET核心中的AssemblyLoadContext来实现。
请记住,使用actor编程范例是一项严肃的设计决策,组件隔离可以通过多种方式实现。因此,如果组件隔离是您决定使用actors的唯一原因,那么您可能需要注意并重新考虑其他选择。
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<MyExtension, MyExtensionProvider>()从代码本身注册和检索这些扩展(也可以使用该方法的签出覆盖)。您也可以直接在HOCON中注册它们-这样当通过HOCON配置提供时,它们将在系统启动时自动启动:
akka.extensions = [
"MyNamespace.MyExtensionProvider1, MyAssembly",
"MyNamespace.MyExtensionProvider2, MyAssembly"
]https://stackoverflow.com/questions/56986261
复制相似问题