如何将您的ASP.NET应用程序部署到活服务器?

我正在寻找不同的技术/工具来部署一个ASP.NET Web应用程序项目( ASP.NET网站)到生产?

我对持续集成构build服务器在某个位置丢弃二进制文件和第一个用户请求到达这些二进制文件的时间之间发生的工作stream程特别感兴趣。

  1. 你正在使用一些特定的工具或只是XCOPY? 应用程序如何打包(ZIP,MSI,…)?

  2. 首次部署应用程序时,如何设置应用程序池和虚拟目录(是否使用手动或使用某种工具创build它们)?

  3. 当静态资源发生变化(CSS,JS或者图像文件)时,你重新部署整个应用程序还是仅仅修改了资源? 如何处理程序集/ ASPX页面更改?

  4. 你跟踪给定应用程序的所有部署版本,万一出现问题,你有程序恢复到以前已知的工作状态的应用程序?

随意完成以前的列表。


以下是我们用来部署ASP.NET应用程序的方法:

  1. 我们将Web部署项目添加到解决scheme,并将其设置为构buildASP.NET Web应用程序
  2. 我们将一个安装项目( 不是 Web安装项目)添加到解决scheme,并将其设置为Web部署项目的输出
  3. 我们添加一个自定义安装操作,并在OnInstall事件中运行一个自定义构build的.NET程序集,该程序集使用System.DirectoryServices.DirectoryEntry在IIS中创build应用程序池和虚拟目录(此任务仅在部署应用程序时首次执行) 。 我们支持IIS中的多个网站,虚拟目录的身份validation以及设置应用程序池的身份。
  4. 我们在TFS中添加一个自定义任务来构build安装项目(TFS不支持安装项目,所以我们不得不使用devenv.exe来构buildMSI)
  5. MSI安装在实时服务器上(如果有先前版本的MSI,它首先被卸载)

我们使用Setup Factory将所有代码部署在MSI中。 如果有什么改变,我们重新部署整个解决scheme。 这听起来像一个CSS文件的矫枉过正,但它绝对保持所有的环境同步,我们确切知道什么是生产(我们部署到所有testing和UAT环境相同的方式)。

我们将滚动部署到实时服务器,所以我们不使用安装程序项目; 我们有更像CI的东西:

  • “活”构build服务器从批准的源(而不是回购的“头”)构build,
  • (在做了备份之后; -p)
  • robocopy发布到分段服务器(“live”,但不在F5集群中)
  • 在临时服务器上进行最后的validation,通常用“主机”黑客尽可能模仿整个事情
  • robocopy / L会自动用来分配下一个“推送”中的更改列表,以提醒任何混乱
  • 作为预定过程的一部分,集群将循环,通过robocopy部署到集群中的节点(当它们在集群外时)

robocopy会自动确保只部署更改。

重新应用程序池等; 我希望这是自动的( 看到这个问题 ),但目前它是手动的。 不过,我真的想改变这一点。

(这可能有助于我们在现场拥有自己的数据中心和服务器场,所以我们不必跨越很多障碍)

网站

部署者: http : //www.codeproject.com/KB/install/deployer.aspx

我发布网站到本地文件夹,压缩,然后通过FTP上传。 服务器上的部署者然后提取zip,replaceconfiguration值(在Web.Config和其他文件中),就是这样。

当然,对于第一次运行,您需要连接到服务器,并设置IIS网站,数据库,但之后发布更新是小菜一碟。

数据库

为了保持数据库的同步,我使用http://www.red-gate.com/products/sql-development/sql-compare/

如果服务器在一堆路由器后面,并且不能直接连接(这是SQL Compare的要求),请使用https://secure.logmein.com/products/hamachi2/创buildVPN。;

我主要将ASP.NET应用程序部署到Linux服务器,并重新部署所有内容,即使是最小的更改。 这是我的标准工作stream程:

  • 我使用一个源代码库(如Subversion)
  • 在服务器上,我有一个bash脚本,执行以下操作:
    • 检查出最新的代码
    • 一个构build(创buildDLL)
    • 将文件过滤到要点(例如删除代码文件)
    • 备份数据库
    • 将文件部署到以当前date命名的目录中的Web服务器
    • 如果部署中包含新架构,则更新数据库
    • 使新安装成为默认安装,以便在下一次安装时进行安装

Checkout是使用Subversion的命令行版本完成的,并且使用xbuild(来自Mono项目的msbuild work-like)完成构build。 大部分的魔法都是在ReleaseIt中完成的。

在我的开发服务器上,我基本上有持续的集成,但在生产端,我实际上是通过SSH进入服务器,并通过运行脚本手动启动部署。 我的脚本被巧妙地称为“部署”,所以这是我在bash提示符下input的内容。 我很有创意。 不。

在生产中,我必须input两次“部署”:一次签出,构build和部署到一个过时的目录,一次使该目录成为默认实例。 由于目录是过时的,我可以简单地通过在相关目录中键入'deploy'来恢复到以前的任何部署。

初始部署需要几分钟,而恢复到之前的版本需要几秒钟的时间。

这对我来说是一个很好的解决scheme,只依赖于三个命令行工具(svn,xbuild和releaseit),数据库客户端,SSH和Bash。

我真的需要在CodePlex上更新ReleaseIt的副本:

http://releaseit.codeplex.com/

简单的XCopy for ASP.NET。 将其压缩到服务器,提取到正确的位置。 对于第一次部署,手动设置IIS

回答你的问题:

  1. 的XCopy
  2. 手动
  3. 对于静态资源,我们只部署已更改的资源。
    对于DLL,我们部署更改后的DLL和ASPX页面。
  4. 是的,是的。

保持它的美好和简单,为我们节省了很多头痛。

你正在使用一些特定的工具或只是XCOPY? 应用程序如何打包(ZIP,MSI,…)?

作为BuildMaster的开发者,这当然是我使用的。 所有应用程序都是在工具中构build和打包的,它们以ZIP文件forms存储在内部。

首次部署应用程序时,如何设置应用程序池和虚拟目录(是否使用手动或使用某种工具创build它们)?

手动 – 我们在工具中创build一个更改控制,提醒我们在应用程序在其testing环境中移动时在未来环境中执行的确切步骤。 这也可以通过一个简单的PowerShell脚本实现自动化,但是我们不会经常添加新的应用程序,所以花费1分钟的时间手动创build站点也是一样的容易。

当静态资源发生变化(CSS,JS或者图像文件)时,你重新部署整个应用程序还是仅仅修改了资源? 如何处理程序集/ ASPX页面更改?

默认情况下,部署工件的过程被设置为只有被修改的文件被传输到目标服务器 – 这包括CSS文件,JavaScript文件,ASPX页面和链接程序集的所有内容。

你跟踪给定应用程序的所有部署版本,万一出现问题,你有程序恢复到以前已知的工作状态的应用程序?

是的,BuildMaster为我们处理所有这些。 恢复大部分与重新执行旧版本升级一样简单,但有时需要手动恢复数据库更改,并且可能会发生数据丢失。 基本的回滚过程在此处详述: http : //inedo.com/support/tutorials/performing-a-deployment-rollback-with-buildmaster

网页设置/安装项目 – 所以你可以很容易地卸载它,如果出现问题

Unfold是我为.net应用程序编写的类似capistrano的部署解决scheme。 这是我们在所有项目中使用的,这是一个非常灵活的解决scheme。 它解决了大多数.net应用程序的典型问题,正如Rob Conery在这篇博客中所解释的。

  • 它带有一个很好的“默认”行为,就是说它为你做了很多标准的东西:从源代码控制,构build,创build应用程序池,设置IIS等等获取代码
  • 基于源代码控制的发布
  • 它有任务挂钩 ,所以默认行为可以很容易地扩展或改变
  • 它有回滚
  • 这是所有的PowerShell ,所以没有任何外部的依赖
  • 它使用PowerShell远程访问远程机器

这里有一个介绍和一些其他的博客文章。

所以要回答上面的问题:

  • 应用程序如何打包(ZIP,MSI,…)?

    Git(或其他scm)是在目标机器上获取应用程序的默认方式。 或者,您可以执行本地构build并通过Powereshell远程连接复制结果

  • 首次部署应用程序时,如何设置应用程序池和虚拟目录(是否使用手动或使用某种工具创build它们)?

    展开使用Powershell的Webpipe理模块configuration应用程序池和网站应用程序。 它允许我们(和您)修改应用程序池或网站的任何方面

  • 当静态资源改变(CSS,JS或者图像文件)时,你重新部署整个应用程序还是只重新部署修改过的资源? 如何处理程序集/ ASPX页面更改?

    是的,展开这一点,任何部署安装在其他人旁边。 这样,当出现问题时,我们可以轻松地回滚。 它还使我们能够轻松地将部署的版本追溯到源代码pipe理版本。

  • 你跟踪给定应用程序的所有部署版本吗?

    是的,展开旧版本。 不是所有的版本,而是一些版本。 它使回滚几乎微不足道。

过去一年我们一直在改进我们的发布stream程,现在我们已经把它放下了。 我使用Jenkins来pipe理我们所有的自动构build和发布,但是我相信你可以使用TeamCity或者CruiseControl。

所以在签入时,我们的“正常”build立做以下几点:

  • jenkins进行SVN更新来获取最新版本的代码
  • NuGet包恢复是在我们自己的本地NuGet存储库上运行的
  • 该应用程序使用MsBuild进行编译。 设置这是一个冒险,因为你需要安装正确的MsBuild,然后ASP.NET和MVC DLL在您的构build框。 (注意,当我在.csproj文件中input<MvcBuildViews>true</MvcBuildViews>来编译视图时,msbuild是随机崩溃的,所以我必须禁用它)
  • 一旦代码被编译,unit testing运行(我使用nunit,但你可以使用任何你想要的)
  • 如果所有的unit testing通过,我停止IIS应用程序池,在本地部署应用程序(只需几个基本的XCOPY命令复制必要的文件),然后重新启动IIS(我有IISlocking文件的问题,这解决了它)
  • 我有单独的web.config文件为每个环境; dev,uat,prod。 (我尝试使用networking转换的东西,很less成功)。 所以正确的web.config文件也被复制
  • 然后我使用PhantomJS来执行一堆UItesting。 它还需要在不同的分辨率(手机,桌面)的一堆屏幕截图和每个屏幕截图与一些信息(页面标题,分辨率)。 Jenkins对处理这些屏幕截图有很大的支持,他们被保存为构build的一部分
  • 一旦集成UItesting通过构build成功

如果有人点击“部署到UAT”:

  • 如果最后一个构build成功,Jenkins会执行另一个SVN更新
  • 该应用程序使用RELEASEconfiguration进行编译
  • 一个“www”目录被创build并且应用程序被复制到它
  • 然后,我使用winscp同步文件系统在构build框和UAT之间
  • 我发送一个HTTP请求到UAT服务器,并确保我得到一个200
  • 此版本在SVN中标记为UATdate时间
  • 如果我们有这么多,build立成功!

当我们点击“Deploy to Prod”时:

  • 用户select一个以前创build的UAT标签
  • 标签被“切换”到
  • 代码被编译并与Prod服务器同步
  • Http请求Prod服务器
  • 此版本在SVN中标记为产品date时间
  • 该版本被压缩并存储

所有的生产完成生产需要约30秒,我非常非常高兴。

颠覆这个解决scheme:

  • 它很快
  • unit testing应该抓住逻辑错误
  • 当一个UI缺陷投入生产时,屏幕截图将有希望显示修改引起的修改
  • UAT和Prod保持同步
  • jenkins向你展示了一个很好的发布历史,包括所有提交消息的UAT和Prod
  • UAT和Prod版本都被自动标记
  • 你可以看到什么时候发布,谁做了

这个解决scheme的主要缺点是:

  • 每当你向Prod发布一个版本,你就需要向UAT发布一个版本。 这是我们做出的有意识的决定,因为我们希望始终确保UAT始终与Prod保持同步。 不过,这是一个痛苦。
  • 有相当多的configuration文件浮动。 我试图把它全部放在Jenkins中,但是有一些支持batch file需要作为这个过程的一部分。 (这些也签入)。
  • 数据库升级和降级脚本是应用程序的一部分,并在应用程序启动时运行。 它工作(主要),但这是一个痛苦。

我很乐意听到其他可能的改进!

早在2009年,这个答案来自于我们,我们使用CruiseControl.net来进行我们的持续集成构build,同时也输出了Release Media。

从那里,我们使用智能同步软件与负载平衡池以外的生产服务器进行比较,然后移动更改。

最后,在validation版本之后,我们运行了一个DOS脚本,主要使用RoboCopy将代码同步到活动的服务器,停止/启动IIS。

在我工作的最后一家公司,我们曾经使用rSyncbatch file进行部署,仅上载自上次上载以来所做的更改。 rSync的美妙之处在于您可以添加排除列表来排除特定的文件或文件名模式。 因此,排除我们所有的.cs文件,解决scheme和项目文件都非常简单。

我们使用TortoiseSVN进行版本控制,所以很高兴能够编写几个SVN命令来完成以下任务:

  • 首先,检查用户是否有最新版本。 如果没有,请提示他们更新或在那里运行更新。
  • 从服务器上下载一个名为“synclog.txt”的文本文件,详细说明SVN用户是谁,他们正在上传什么版本号以及上传的date和时间。 为当前上传附加一个新行,然后将其与已更改的文件一起发送回服务器。 这使得查找哪个版本的站点可以非常容易地回滚,以避免上传导致问题。

除此之外,还有第二个batch file只是检查活动服务器上的文件差异。 这可以突出显示有人上传但不会将更改提交给SVN的常见问题。 结合上面提到的同步日志,我们可以找出谁是可能的罪魁祸首,并要求他们进行工作。

最后,rSync允许您备份在上传过程中被replace的文件。 我们把它移动到备份文件夹中如果你突然意识到某些文件不应该被覆盖,你可以find该文件夹​​中每个文件的最后备份版本。

虽然这个解决scheme当时感觉有点笨拙,但是在上传方法不够优雅或者简单的环境中工作时,我却感受到了更多的东西(例如,远程桌面,复制和粘贴整个站点) 。

我build议不要只覆盖现有的应用程序文件,而是为每个版本创build一个目录,并将IIS应用程序重新指定到新path。 这有几个好处:

  • 如果需要快速恢复
  • 无需停止IIS或应用程序池以避免locking问题
  • 没有旧文件导致问题的风险
  • 或多或less的零停机时间(通常只是暂停在新的AppDomain初始化)

我们遇到的唯一问题是资源被caching,如果您不重新启动应用程序池并依靠自动appdomain开关。