.NET程序集的热部署

7
我们在生产服务器上运行一个作为Windows服务的应用程序。该应用程序分为几个程序集,大多数都在部署边界上。我想简化应用程序程序集的热修复部署。目前,我执行以下步骤来部署热修复(我们有一个生产环境的副本用于暂存,因此必须进行两次操作):
  1. 登录服务器
  2. 停止服务
  3. 备份当前已部署的dll
  4. 使用热修复替换(将热修复复制到现有dll上)
  5. 重新启动服务
  6. 在出现意外负载错误的情况下回滚(尚未发生)
我认为我想要的是上传(SFTP)dll到预设文件夹并让应用程序捡起新的dll。
我考虑的一种解决方案是在服务器上运行一个单独的服务。让我们称之为热修复部署服务。它会监视新文件的文件系统,并执行上述列表中的步骤2-6。
如果您有任何见解,我们非常感谢。只要它们减少部署摩擦力,我也可以接受其他替代方案。
3个回答

5
拥有一个独立的服务可能是您最好的选择。
您可以将所有内容放在单个服务中。但要使服务能够自我更新,需要实现一些技巧,这有点难以实现。
您需要做的是:让服务作为一个非常轻量级的外壳服务启动。然后它可以启动一个单独的、隔离的 AppDomain,并让该 appdomain 加载您的服务的程序集并初始化和运行。
稍后,当您想要更新时(可以通过服务可以捕获的任何事件触发,包括通过 FileSystemWatcher 将新程序集复制到更新文件夹中,通过网络明确告知等),它需要触发一种方式来告诉内部 AppDomain 的类型停止,然后卸载 AppDomain。此时,它可以执行上述步骤3和4。然后,只需重新加载 AppDomain,重新运行其初始化等即可。
由于服务将位于单独的 AppDomain 中,因此所有这些都可以在一个可执行文件中完成,而无需停止服务。当卸载 AppDomain 时,它加载的程序集也会被卸载。
唯一的要求是不要从构建的 AppDomain 向主 AppDomain 传递任何类型,否则您将把程序集加载到主 AppDomain 中。这将防止您能够在运行时更新它们。

1
ShadowCopyFiles 在这里非常重要。 - Jason Punyon
是的,虽然备份要求可能在这种特定情况下不那么重要。 - Reed Copsey
备份步骤并不是硬性要求,只是我为了能够快速回滚而执行的步骤。我对ShadowCopyFiles不熟悉,需要进一步了解。 - Kim Major

2

我们使用PowerShell脚本从构建服务器远程停止服务,复制新文件并重新启动服务。


我们几乎完全从CruiseControl.NET实现了这一点。(没有PowerShell)。 - Jason Punyon

1
我建议你可以考虑使用Castle Windsor作为“热插拔”程序集的好选择。
这是一个先进且得到良好支持的IoC/DI框架,可以帮助你完成你提到的许多任务,但实际上将文件移动到目标机器上需要另外处理。不过,CW可以很好地处理实际的管道工作。

我们已经在使用一个IoC容器(Unity),但我不确定它如何热交换已加载的类型。Castle 在这方面有什么东西吗?(快速查看网站没有发现任何信息) - Kim Major
是的。你需要更深入地挖掘一些,但是热插拔是CW的核心目标之一(至少在我上次查看时是这样)。Unity不支持热插拔?令人惊讶。但是你已经在使用DI框架这个事实应该帮助你相当容易地进行迁移。 - Paul Sasik
我猜这取决于“热插拔”的定义。例如,如果您有接口的几个实现,您可以解析任何给定的实现。但是,在应用程序使用已解析并正在使用的具体实现之后,我需要替换它。我没有想到在Unity中寻找这个功能,但我非常确定您无法做到这一点。在构建容器并加载类型之后,它基本上会停留在应用程序域中(除非我漏掉了什么)。 - Kim Major
通过热插拔,我指的是能够替换代码并实例化和运行,就像您所期望的那样。是的,启用热插拔取决于仔细的应用程序域管理,因为这是在 .Net 中加载/卸载模块的粒度。 - Paul Sasik
1
@Kim:看一下这篇博客文章:http://ayende.com/Blog/archive/2007/09/22/Introducing-MonoRail.HotSwap.aspx 我对不同的Castle项目有点困惑。自从上次使用它们以来,它们已经被重新整理过了。 - Paul Sasik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接