How do you deploy your ASP.NET applications to live servers?
我正在寻找不同的技术/工具,您用来部署一个ASP.NET Web应用程序项目(而不是ASP.NET网站)到生产?
我特别感兴趣的是,在您的持续集成构建服务器将二进制文件放在某个位置和第一个用户请求访问这些二进制文件之间发生的工作流。
您是使用某些特定的工具还是只使用Xcopy?应用程序是如何打包的(zip、msi等)?
首次部署应用程序时,如何设置应用程序池和虚拟目录(是手动创建还是使用某种工具创建)?
当静态资源发生更改(css、js或image文件)时,是重新部署整个应用程序,还是只重新部署修改后的资源?程序集/ASPX页何时更改如何?
是否跟踪给定应用程序的所有已部署版本,如果出现问题,是否有将应用程序还原到以前已知工作状态的过程?
请随意完成上一个列表。
下面是我们用来部署ASP.NET应用程序的内容:
我们使用安装工厂在MSI中部署了所有代码。如果有什么需要改变的话,我们就重新部署整个解决方案。对于一个CSS文件来说,这听起来有点过头了,但它绝对能保持所有环境的同步,而且我们确切地知道什么是在生产环境中(我们以相同的方式部署到所有测试和UAT环境中)。
我们对实时服务器进行滚动部署,因此不使用安装程序项目;我们有一些更像CI的东西:
- 从批准的源(而不是repo的"头")构建"实时"构建服务器
- (备份后;-p)
- robocopy发布到临时服务器("live",但不在f5集群中)
- 在临时服务器上完成的最终验证,通常使用"主机"黑客来尽可能地模拟整个事件。
- robocopy/l自动用于在下一个"push"中分发更改列表,以提醒任何goof
- 作为计划过程的一部分,集群被循环,通过robocopy部署到集群中的节点(当它们不在集群中时)
Robocopy自动确保只部署更改。
关于应用程序池等;我希望这是自动的(见这个问题),但目前它是手动的。不过,我真的想改变这一点。
(我们有自己的数据中心和服务器场"现场"可能会有所帮助,因此我们不必跨越许多障碍)
网站
Deployer:http://www.codeproject.com/kb/install/deployer.aspx
我将网站发布到本地文件夹,压缩它,然后通过ftp上传。然后,服务器上的Deployer提取zip,替换config值(在web.config和其他文件中),就这样。
当然,对于第一次运行,您需要连接到服务器并设置IIS网站、数据库,但是在发布更新之后,就很容易了。
数据库
为了保持数据库的同步,我使用http://www.red-gate.com/products/sql-development/sql-compare/
如果服务器位于一堆路由器后面,而您无法直接连接(这是SQL比较的要求),请使用https://secure.logmein.com/products/hamachi2/创建VPN。
我主要将ASP.NET应用程序部署到Linux服务器上,并重新部署所有内容,即使是最小的更改。这是我的标准工作流程:
- 我使用源代码存储库(如Subversion)
- 在服务器上,我有一个bash脚本,它执行以下操作:
- 查看最新代码
- 执行生成(创建DLL)
- 将文件过滤到基本内容(例如删除代码文件)
- 备份数据库
- 将文件部署到名为当前日期的目录中的Web服务器
- 如果部署中包含新架构,则更新数据库
- 使新安装成为默认安装,以便下次点击时使用
签出是通过命令行版本的Subversion完成的,而构建是通过Xbuild完成的(msbuild的工作类似于mono项目)。大部分魔法都是在释放中完成的。
在我的dev服务器上,我基本上具有持续集成,但在生产方面,我实际上是通过ssh进入服务器,并通过运行脚本手动启动部署。我的脚本被巧妙地称为"deploy",所以这就是我在bash提示下键入的内容。我很有创造力。不是。
在生产环境中,我必须键入"deploy"两次:一次是签出、生成并部署到一个日期为的目录,另一次是将该目录设置为默认实例。由于目录是有日期的,所以只需在相关目录中键入'deploy',就可以恢复到以前的任何部署。
初始部署需要几分钟时间,恢复到以前的版本需要几秒钟时间。
对于我来说,这是一个很好的解决方案,它只依赖于三个命令行实用程序(SVN、Xbuild和Releaseit)、DB客户机、SSH和bash。
我真的需要在codeplex上更新releaseit的副本:
网址:http://releaseit.codeplex.com/
Are you using some specific tools or just XCOPY? How is the application packaged (ZIP, MSI, ...)?
作为buildmaster的开发人员,这是我自然使用的。所有应用程序都作为工件构建和打包在工具中,这些工件在内部存储为zip文件。
When an application is deployed for the first time how do you setup the App Pool and Virtual Directory (do you create them manually or with some tool)?
手动-我们在工具中创建一个变更控制,它提醒我们在应用程序通过其测试环境时在未来环境中执行的确切步骤。这也可以通过一个简单的PowerShell脚本实现自动化,但我们不会经常添加新的应用程序,因此手动创建站点所需的1分钟时间同样容易。
When a static resource changes (CSS, JS or image file) do you redeploy the whole application or only the modified resource? How about when an assembly/ASPX page changes?
默认情况下,部署工件的过程被设置为只将修改过的文件传输到目标服务器-这包括CSS文件、JavaScript文件、ASPX页面和链接程序集的所有内容。
Do you keep track of all deployed versions for a given application and in case something goes wrong do you have procedures of restoring the application to a previous known working state?
是的,buildmaster为我们处理所有这些。恢复主要与重新执行旧的生成升级一样简单,但有时需要手动恢复数据库更改,并且可能会发生数据丢失。下面详细介绍了基本回滚过程:http://inedo.com/support/tutorials/performing-a-deployment-rollback-with-buildmaster
回答您的问题:
保持它的美好和简单迄今为止已经节省了我们很多头痛。
简单的Xcopy for ASP.NET。把它压缩,sftp到服务器,提取到正确的位置。对于第一次部署,手动设置IIS
在过去的一年里,我们一直在改进我们的发布过程,现在我们已经成功了。我正在使用Jenkins管理我们所有的自动化版本和发布,但我确信您可以使用TeamCity或CruiseControl。
因此,在签入之后,我们的"正常"构建将执行以下操作:
- Jenkins进行SVN更新以获取最新版本的代码
- nuget包还原是针对我们自己的本地nuget存储库运行的。
- 应用程序是使用msbuild编译的。设置此设置是一种冒险,因为您需要安装正确的msbuild,然后在构建框上安装ASP.NET和MVC DLL。(顺便说明一下,当我在.csproj文件中输入
以编译视图时,msbuild随机崩溃,因此我必须禁用它)true - 编译完代码后,运行单元测试(我正在为此使用nunit,但您可以使用任何您想要的东西)
- 如果所有单元测试都通过,我将停止IIS应用程序池,在本地部署该应用程序(只需几个基本的xcopy命令就可以复制必要的文件),然后重新启动IIS(我在IIS锁定文件方面遇到了问题,解决了这个问题)。
- 对于每个环境,我都有单独的web.config文件;dev、uat、prod(我尝试使用web转换工具,但收效甚微)。因此,正确的web.config文件也被复制到
- 然后我使用phantomjs来执行一系列UI测试。它还以不同的分辨率(移动、桌面)拍摄大量截图,并在每个截图上贴上一些信息(页面标题、分辨率)。詹金斯非常支持处理这些截图,它们作为构建的一部分保存。
- 一旦集成UI测试通过,构建就成功了。
如果有人点击"部署到UAT":
- 如果最后一次构建成功,Jenkins会进行另一次SVN更新
- 使用发布配置编译应用程序
- 创建"www"目录并将应用程序复制到其中
- 然后我使用winscp在build box和uat之间同步文件系统。
- 我向UAT服务器发送一个HTTP请求,并确保返回一个200
- 此版本在SVN中标记为UAT日期时间。
- 如果我们做到了这一点,构建就是成功的!
当我们单击"部署到产品"时:
- 用户选择以前创建的UAT标记
- 标签被"切换"到
- 代码被编译并与prod服务器同步
- 对Prod服务器的HTTP请求
- 此版本在SVN中标记为prod datetime
- 释放被压缩并存储
全部建成投产大约需要30秒,我非常非常高兴。
此解决方案的优点:
- 它很快
- 单元测试应该捕获逻辑错误
- 当一个用户界面bug投入生产时,屏幕截图将有希望显示是什么版本引起了它。
- UAT和Prod保持同步
- Jenkins向您展示了UAT的一个伟大的发布历史,并用所有提交消息来提示您。
- UAT和Prod版本都是自动标记的
- 你可以看到什么时候发布,是谁发布的
此解决方案的主要缺点是:
- 每当你做一个发布来刺激你需要做一个发布到UAT。这是我们做出的一个有意识的决定,因为我们希望始终确保UAT与Prod保持同步。不过,这是一种痛苦。
- 有相当多的配置文件漂浮在周围。我已经尝试将其全部保存在Jenkins中,但是在这个过程中需要一些支持批处理文件。(这些也是签入的)。
- 数据库升级和降级脚本是应用程序的一部分,在应用程序启动时运行。它起作用(大部分),但很痛苦。
我很乐意听到其他可能的改进!
Unfold是我为.NET应用程序编写的类似capistrano的部署解决方案。它是我们在所有项目中使用的,是一个非常灵活的解决方案。它解决了.NET应用程序的大多数典型问题,正如RobConery在这篇博客文章中所解释的。
- 它具有良好的"默认"行为,从某种意义上说,它为您做了很多标准工作:从源代码管理中获取代码、构建、创建应用程序池、设置IIS等
- 基于源代码管理中的内容发布
- 它具有任务挂钩,因此可以轻松地扩展或更改默认行为
- 它已经回滚了。
- 都是PowerShell,所以没有任何外部依赖项
- 它使用PowerShell远程处理访问远程计算机
这里有介绍和其他一些博客文章。
因此,要回答上述问题:
应用程序是如何打包的(zip、msi等)?
Git(或另一个SCM)是在目标计算机上获取应用程序的默认方法。或者,您可以执行本地生成并通过powereshell远程处理连接复制结果。
首次部署应用程序时,如何设置应用程序池和虚拟目录(是手动创建还是使用某种工具创建)?
Unfold使用PowerShell的WebAdministration模块配置应用程序池和网站应用程序。它允许我们(和您)修改应用程序池或网站的任何方面
当静态资源发生更改(css、js或image文件)时,是重新部署整个应用程序,还是只重新部署修改后的资源?程序集/ASPX页何时更改如何?
是展开执行此操作,任何展开都安装在其他展开旁边。这样我们可以很容易地回滚当出了问题。它还允许我们轻松地跟踪部署的版本源代码管理修订。
是否跟踪给定应用程序的所有已部署版本?
是的,展开可以保留旧版本。不是所有版本,而是一些版本。这使得回滚几乎是微不足道的。
Web安装/安装项目-以便在出现问题时轻松卸载
早在2009年,这个答案来源于CruiseControl.net,我们使用CruiseControl.net进行持续集成构建,它也输出了发布媒体。
从那里,我们使用智能同步软件与不在负载平衡池中的生产服务器进行比较,并将更改上移。
最后,在验证了版本之后,我们运行了一个DOS脚本,它主要使用robocopy将代码同步到活动服务器上,并在运行时停止/启动IIS。
我建议您不仅要覆盖现有的应用程序文件,还要为每个版本创建一个目录,并将IIS应用程序重新导入新路径。这有几个好处:
- 如果需要,可以快速恢复
- 无需停止IIS或应用程序池以避免锁定问题
- 没有旧文件导致问题的风险
- 或多或少零停机(通常只是在新AppDomain初始化时暂停)
我们遇到的唯一问题是,如果不重新启动应用程序池并依赖于自动AppDomain开关,那么资源将被缓存。
在我为之工作的最后一家公司,我们使用rsync批处理文件部署,只上载自上次上载以来所做的更改。rsync的好处在于,可以添加排除列表来排除特定的文件或文件名模式。例如,排除所有.cs文件、解决方案和项目文件非常简单。
我们使用Tortoissesvn进行版本控制,因此能够编写几个svn命令来完成以下任务是很好的:
- 首先,检查用户是否有最新版本。如果没有,要么提示他们更新,要么就在那里运行更新。
- 从名为"synclog.txt"的服务器下载一个文本文件,详细说明SVN用户是谁、他们上载的版本号以及上载的日期和时间。为当前上载附加一行新行,然后将其连同更改的文件一起发送回服务器。这使得我们很容易找到要回滚到哪个版本的网站,因为上传会导致问题。
除此之外,还有第二个批处理文件,用于检查Live服务器上的文件差异。这可以突出一个常见的问题,即有人将上载但不将更改提交到SVN。结合上面提到的同步日志,我们可以找出可能的罪魁祸首,并要求他们提交他们的工作。
最后,rsync允许您备份上传过程中替换的文件。我们让它把它们移到备份文件夹中,这样,如果您突然意识到某些文件不应该被覆盖,您可以找到该文件夹中每个文件的最后一个备份版本。
当我在上传方法不那么优雅或简单的环境中工作时(例如,远程桌面,复制和粘贴整个站点),解决方案在当时感觉有点笨拙,但我开始更加欣赏它。