.NET热部署/取消部署捆绑代码。如何?哪个容器?

时间:2017-12-01 10:15:25

标签: c# .net

我们是.NET世界的新手,并在Nancy

之上构建了一个小型C#应用程序

我们正在寻找一种“打包”应用程序代码的方法,以便我们可以在最小的基于Nancy的容器(或您可能建议的任何其他适当的容器)之上以编程方式热部署和取消部署它

我们如何在.NET世界中这样做?

在JVM世界中,一种方法是打包部署在servlet引擎(通常是Jetty或Tomcat)之上的Web应用程序资源(war)。还有其他解决方案(微容器,直接使用类加载器等)。我们正在寻找一个等效的.NET范例。

12月5日编辑

似乎有关于构建Assemblies和使用Assembly.LoadFromString等方法的解决方案。

这仍然看起来非常简单,我们正在寻找一个C#库/框架来帮助加载/卸载

4 个答案:

答案 0 :(得分:2)

卸载代码的唯一方法是卸载整个AppDomain。这意味着您可能希望为动态加载的每个程序集创建一个新的AppDomain。

此示例为您提供了如何创建新AppDomain以及如何调用加载到另一个AppDomain中的代码的起点: https://stackoverflow.com/a/2648592/540832

答案 1 :(得分:1)

您可以将代码加载到单独的AppDomain中,并使用卷影复制进行热重新加载。假设您有这样的南希应用程序:

static void Main(string[] args) {
    using (var host = new NancyHost(new Uri("http://localhost:34455"))) {
        host.Start();
        Console.WriteLine("started");
        Console.ReadKey();
    }
}

public class SampleModule : Nancy.NancyModule {
    public SampleModule() {
        Get["/"] = _ => "Hello World!";
    }
}

并且您希望能够在不重新启动主机进程的情况下更新它。你可以这样做(警告 - 非生产就绪代码,只是样本)。创建另一个这样的应用程序:

static void Main() {
    while (true) {
        var setup = new AppDomainSetup();
        setup.ApplicationBase = @"Path to directory with your nancy app";
        setup.ShadowCopyFiles = "true";
        var domain = AppDomain.CreateDomain("Nancy", new Evidence(), setup); 
        domain.ExecuteAssembly(@"Path to your nancy app exe");
        AppDomain.Unload(domain);
    }
}

然后启动第二个(主机)应用程序。它将创建新的应用程序域并在其中启动您的nancy应用程序。现在,您可以在主机应用程序运行时更新您的nancy应用程序(在该文件夹中 - 由于影子复制,文件未锁定)。要应用更新 - 按主机应用程序中的任意键。这将删除旧版本的app域,并使用新版本创建新的应用域,而无需重新启动过程。

使用此技术,您可以通过FileSystemWatcher在您的应用程序中查看目录,并在更改应用程序文件时替换app域。您还可以通过首先将新的appdomain加载到启动南希主机之前的点,然后拆除旧的应用程序域,然后在新的应用程序域中启动nancy主机来最小化停机时间。

答案 2 :(得分:1)

不幸的是,它不是.NET世界中的典型任务,因此您不必找到一个简单广泛使用的插件解决方案。

Managed Extensibility Framework,后来称为Microsoft.Composition,后来称为System.Composition。 请检查How to discover new MEF parts while the application is running?,因为它可能是您正在寻找的解决方案。

using System.Composition with .NET Core也有一些文章。

使用像AutoFac这样的IoC框架,自己实现插件系统并不难。

假设您的应用程序具有可以调用服务的Nancy模块,并且这些服务实现了您可能想要动态更改的实际逻辑。这使得服务本质上是一个插件。我们的想法是让IoC为每次http调用返回一个更新的服务实例。

  1. 您可以使用作用域服务提供者\ factory,它将使用反射从刷新的程序集中解析和创建服务实例。
  2. 您可以在程序集重新加载时刷新服务集合容器(或创建新的IoC容器)。
  3. 可悲的是,在这两种情况下,您都必须手动检测已更改的程序集文件,但这对于FileSystemWatcher类来说是一项微不足道的工作。

    此外,在某些IoC库中,更新运行时的依赖关系并不是一种好习惯,例如,请查看here

答案 3 :(得分:0)

如果您使用的是Windows / IIS,则可以使用MSDeploy更新Web应用程序,而无需停机。请注意,它不会保留任何内存状态,因为它将在新的AppDomain中启动新版本,同时将卸载旧的AppDomain。