单独 AppDomain 中的 Service Fabric Actor

Service Fabric Actors in a separate AppDomain

我正在考虑一种设计,其中 "DynamicActors" 能够从动态创建的 AppDomain 中的给定文件共享加载和执行任意代码。像这样的伪代码

class DynamicActor: Actor, IDynamicActor

  Task ExecuteAsync(string assemblyName, string typeName)      
    AppDomain appDomain = AppDomain.CreateDomain(...)
    appDomain.SetData("AssemblyName", assemblyName)
    appDomain.SetData("TypeName", typeName)
    appDomain.DoCallBack(<load the type and execute a predefined / interface method>)

理由是能够经常更新动态加载的代码,而不需要升级 DynamicActors 服务。

总的来说这是个好主意吗?

独立AppDomain中的动态加载代码是否可以使用SF运行时,例如创建actor代理并调用其方法?

谢谢,

帕洛

如果您只是想要一种升级 actor 服务代码的方法,这听起来不是个好主意。应用程序升级是 Service Fabric 中的核心场景,而 Service Fabric 在这方面做得很好。如果您自己设计了动态程序集加载,则必须考虑版本控制、运行状况监控、安全滚动升级、回滚等,所有这些 Service Fabric 都已经做到了。

如果您正在寻找用户可以 运行 插件的 "plug-in" 模型,我可能建议查看专为此目的设计的 Managed Extensibility Framework

在考虑了 Vaclav 的回答后,我决定采用下面描述的“所有 Service Fabric”路线。在此之前,先说一下应用场景:

  • 将有 数百个 程序集实现无人值守的 ETL 类型“任务”。
  • 任务将定期执行,持续时间以秒为单位,最多一分钟。
  • 任务程序集必须单独进行版本控制(包括它们的依赖项),并且会经常进行版本控制。
  • 任务程序集不得依赖于 SF 程序集。

真正的目标是使用 Service Fabric 群集来执行可通过文件共享访问的任何代码。

我已经在 GitHub - https://github.com/PaloMraz/ServiceFabricDynamicTaskExecution.

上提供了一个示例概念验证解决方案

注意:在下面的讨论中,术语“任务”是指任何public class 具有public 默认构造函数公开public 具有以下签名的方法:

Task<string> ExecuteAsync(string parameters)

样本溶液由以下成分组成:

TaskExecutorActors 包含具有单个 ExecuteTaskAsync 方法的 TaskExecutorActor actor 的服务:

Task<string> ExecuteTaskAsync(string taskAssemblyPath, string taskClassName, string taskParameters);

该实现使用 Activator.CreateInstanceFrom API 在指定的程序集中实例化 class,然后使用指定的参数调用 ExecuteAsync 方法。

TaskExecutorGateway 是一种无状态服务,它公开 Web API HTTP 端点以从集群外部调用。

TaskExecutorClientLib 是一个 class 库,其中包含 TaskExecutorClient class 以及用于轻松调用 TaskExecutorGateway HTTP 端点的方法:

Task<string> ExecuteTaskAsync(string taskAssemblyPath, string taskClassName, string taskParameters)

此方法在 TaskExecutorGateway 中的实现使用传入的 taskAssemblyPath 的 目录名 创建 TaskExecutorActors 服务的唯一实例,以从程序集中加载和执行任务目录。

任务程序集一旦被TaskExecutorActors服务进程加载,就被锁定,无法被替换。为了替换程序集,TaskExecutorClient 公开了另一种方法:

Task<string> UnloadTaskAssembliesAsync(string assembliesFolderPath)

实现(在 TaskExecutorGateway 内部)只是删除按需创建的“目录绑定”TaskExecutorActors 服务,从而拆除其进程并释放加载的程序集。

该解决方案包含两个示例任务程序集和一个 TaskExecutorTestConsole 控制台项目,其中包含一些用于整个基础结构的代码。

请注意:TaskExecutorGateway 通过端口 80 公开 Web API,因此请确保在 ServiceManifest.xml 和 TaskExecutorTestConsole 示例代码中更改此设置如果您的本地开发集群中有其他应用程序已经在侦听端口 80。

您如何看待这种 SF 使用模式?