使用Web Deploy发布ASP.NET MVC2站点

时间:2011-02-03 10:43:12

标签: asp.net-mvc visual-studio performance deployment web-deployment-project

我目前使用Web Deploy http://learn.iis.net/page.aspx/346/web-deploy/发布我的MVC2应用。它曾经运作良好,但现在它已经到了我无法继续使用它的地步:

当MVC应用程序很小并且只有少数用户时,它很容易发布。只需在Visual Studio中右键单击该项目,然后选择“发布”。而且因为只有少数用户很容易找到没有人使用该网站进行快速更新的时间。

然后,应用程序变得更大,并有更多的用户。 “发布”操作开始时间越来越长,偶尔会超时。即使我在部署之前回收了应用程序池,它仍然需要很长时间。

此外,当没有人使用该网站时,更难找到时间,因此可以在不影响任何人的情况下完成更新。

然后“发布”操作每次都开始超时,我不得不根据之前未回答的问题切换到手动部署:Visual Studio 2010 - web deploy times out - what to do?

现在手动部署的时间越来越长,从5分钟到20分钟不等。并且用户数量显着增加,因此部署总是会影响某人(响应时间慢,超时,站点不可用等)

那我该怎么办?有没有比使用Web部署更好的替代方案?

编辑:

今天的部署花了18分钟才发布了49个已更改的文件。这种情况很荒谬,是我们网站目前最大的弱点之一。因此,我希望能够解决这个问题,从而获得了不错的奖金。

可能导致解决方案的其他一些问题:

  • 为什么只需更改几个文件就需要这么长时间?
  • 为什么Web部署zip始终包含整个代码库而不只是更改文件?
  • 为什么我不自己手动复制已更改的文件并跳过整个Web部署?但很难手动确定哪些文件已更改。我使用SVN - 它是否只能输出两个分支之间发生变化的文件?
  • 我应该问什么其他问题,但还没想过呢?

回答答案:

Re:http://www.troyhunt.com/2010/11/you-deploying-it-wrong-teamcity_24.html这正是我进行部署的方式,也是一种理想的方法。 Web部署可以正确识别哪些文件已更改,但它会超时并且不会发生发布。解决方案中大约有2500个文件,可能需要很长时间才能确定哪些文件发生了变化?或者可能是发布的超时值很短,只需上传15mb的zip文件即可使用所有时间。

我确实可以完全控制服务器,它确实支持Web部署。实际上有2台服务器:主服务器和冗余服务器,我们会在第一次服务器崩溃时做好准备。因此,任何解决方案都必须易于部署到多个服务器(Web部署是理想的,直到它停止工作)。

为每个版本创建一个新文件夹,然后只是将IIS更改为指向该新文件夹的建议听起来像是在发布期间会导致更短的停机时间/慢速时间。但这是一个非常手动的过程,我更喜欢更自动化的东西。

编辑#2

我已经设法缩小范围,并找到它确切的缓慢位置 - 但不是为什么。这来自部署日志:

[9/02/2011 12:11:56 a.m.] Performing synchronization pass #1.
[9/02/2011 12:11:56 a.m.] Parameter entry 'IIS Web Application Name/1' is applicable to 'iisApp/C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp' because of its scope.
[9/02/2011 12:11:56 a.m.] Parameter entry 'IIS Web Application Name/2' is applicable to 'setAcl/C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp' because of its scope.
[9/02/2011 12:11:56 a.m.] Parameter entry 'IIS Web Application Name/2' is applicable to 'setAcl/C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp' because of its scope.
[9/02/2011 12:11:56 a.m.] Parameter entry 'Add write permission to App_Data Folder/1' is applicable to 'setAcl/C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp\App_Data' because of its scope.
[9/02/2011 12:11:56 a.m.] Source createApp (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp) does not match destination (Default Web Site/virtual-dir/) differing in attributes (isDest['False','True']). Update pending.
[9/02/2011 12:11:56 a.m.] Update operation on createApp (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp) skipped because of rule CreateApplicationRule.
[9/02/2011 12:11:56 a.m.] Source filePath (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp\App_Data\Create.sql) does not match destination (Default Web Site/virtual-dir/App_Data\Create.sql) differing in attributes (size['259691','259697'],lastWriteTime['02/08/2011 10:45:20','02/06/2011 03:48:16']). Update pending.

[400 lines of file updates skipped, time expired 2 seconds ....]

[9/02/2011 12:11:58 a.m.] Delete operation on filePath (Default Web Site/v2/zzz_app_offline.htm) skipped because of rule DoNotDeleteRule.
[9/02/2011 12:11:58 a.m.] Source setAcl (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp) does not match destination (Default Web Site/virtual-dir/) differing in attributes (isDest['False','True'],setAclUser,setAclAccess). Update pending.
[9/02/2011 12:11:58 a.m.] Updating setAcl (Default Web Site/virtual-dir/).
[9/02/2011 12:13:47 a.m.] Source setAcl (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp) does not match destination (Default Web Site/virtual-dir/) differing in attributes (isDest['False','True'],setAclUser,setAclAccess). Update pending.
[9/02/2011 12:13:47 a.m.] Updating setAcl (Default Web Site/virtual-dir/).
[9/02/2011 12:17:11 a.m.] Source setAcl (C:\src\Site.2010\Site.UI\obj\Release\Package\PackageTmp\App_Data) does not match destination (Default Web Site/virtual-dir//App_Data) differing in attributes (isDest['False','True'],setAclUser,setAclAccess). Update pending.
[9/02/2011 12:17:11 a.m.] Updating setAcl (Default Web Site/virtual-dir//App_Data).
[9/02/2011 12:17:11 a.m.] The dependency check 'DependencyCheckInUse' found no issues.
[9/02/2011 12:17:11 a.m.] The synchronization completed in 1 pass(es).

缓慢的原因是"Updating setAcl"组件。我正在检查开发盒和服务器盒的ACL,看看有什么不同。但是,将ACL从开发框复制到服务器框似乎是一个非常糟糕的主意!我已经在服务器上设置了ACL。

8 个答案:

答案 0 :(得分:3)

来自您提供的信息的@JK感觉就像是超时问题。我同意@TroyHunt 2500文件中的15兆应该快速部署。特别是输出在应用ACL时显示延迟(无论是否需要更改)。如果是我,我会开始做一些非Web部署健康检查。想到了一些想法

  • 是域或工作组中的网络服务器吗?
  • dcdiag显示什么?
  • netdiag显示什么?
  • 是同一域中的开发框和prod框?

您是否有可能尝试应用不再存在,被禁用或来自Web服务器域以外的域的用户或组?您的组织可能具有子域或域信任的域层次结构,这些域有效,但在生产数据中心中阻止通信。

我想我也会手动查看ACL并查看是否有无法解析的条目(它们在解决之前显示为SIDS)。

HTH, -eric

答案 1 :(得分:2)

我首先尝试隔离发生超时的位置。你已经提到了一个带有2,500个文件的15MB压缩文件,这对我来说并不特别大。您是否尝试在Visual Studio中创建部署包,然后直接在服务器上运行它?这将消除图片中的网络延迟,这在超时方面是一个非常基本的变量。

至于为什么需要上传整个应用程序的zip,你需要记住实际识别的内容已经发生了变化,后续部署到IIS中的所有内容都发生在服务器上。在本地计算机上调用镜头不是Visual Studio或msdeploy。

至于为什么你不只是手动复制已更改的文件,它在我引用的博客文章中进行了总结,但简而言之,它很费力且容易出错。这意味着你需要有意识地完成“我的2,500个文件中的哪一个刚改变”的思维过程,而不是简单地说“让我的目标网站与我的开发版本匹配”。你没有提到你是否发布了web.config,但显然配置转换是简单的CTRL-C然后CTRL-V方法繁琐的另一个重要原因。

尝试直接从SVN进行更改也存在风险。您的第一个问题是,如果您要发布适当的更改,则需要对从更新的修订的完整性和准确性完全放心。然后,您将尝试将这些内容同步到目标,然后您回到上一段中提出的相同问题。另一个大问题是版本控制对象代码总是很讨厌;你将与​​项目中的任何其他人处于永久性的冲突状态,而VCS根本不打算以这种方式运作。

我的建议是专注于解决问题的根本原因 - Web部署超时 - 而不是简单地尝试解决问题。仅手动发布更改或使用IIS绑定搞乱只会给您带来更多麻烦,并且在短期内会有更多工作。了解如何共享创建包的结果,将其复制到服务器然后在本地执行,我们将从那里开始。一旦你按照设计工作,你应该看到部署时间不超过几分钟,站点中断只需几秒钟。

BTW - 您可能还想添加PC和服务器之间的延迟,以及通过HTTP传输15MB文件通常需要多长时间。

答案 2 :(得分:1)

如果您可以控制服务器,那么一个非常好的选择就是手动上传zip文件。解压缩然后使用IIS管理器指向新的代码库。这样,停机时间应该是最小的。如果出现问题,您的最后一个版本保持不变,并且可以再次将IIS指向该文件夹。

在共享主机上,这不会有效。也许有一些方法可以通过上传代码然后重命名文件夹以使其指向新文件来调整相同的策略。

无论如何,似乎Web部署应支持仅发送已更改的内容。但我认为在这种情况下你需要支持Web部署:http://www.troyhunt.com/2010/11/you-deploying-it-wrong-teamcity_24.html

如果您没有,我猜您可以使用脚本来检测SVN中的修改。以下是有关如何查找已更改文件的一些信息:http://blog.lysender.com/2010/11/svn-list-modified-files-between-revisions/您必须记住代码文件已编译为dll文件,因此我可以想象如下:

  1. 发布网站(或者使用临时服务器中的文件,无论您的情况最有意义)
  2. 让脚本构建要修改的文件列表(将代码文件转换为其dll)
  3. 使用可通过命令行控制的ftp来推送更改。

答案 3 :(得分:1)

您可以考虑的其他一些选项:

1)每次部署到一个新目录,然后使用IIS在目录之间切换。

2)为二进制文件使用单独的Subversion存储库。 svn-load-dirs.pl可以将二进制文件加载到subversion中,并且可以正确标记已添加,删除或更改的文件。您可以在自动构建过程结束时运行svn load-dirs。构建过程是检查此存储库的唯一“用户”,并且生产服务器是唯一检查它的位置,因此没有版本控制冲突。

要部署你,只需从二进制subversion存储库svn更新工作目录。它以原子方式有效地仅复制已更改的文件(即,如果下载失败,则不会替换任何文件)。如果您在部署后立即发现问题,则可以快速返回到先前版本。如果要更新单个aspx文件,可以对该单个文件执行有针对性的svn更新。

如果您在服务器上安装了TortoiseSVN,您还可以立即看到是否有人更改了服务器上的任何文件,而无需通过正确的build-> checkin->部署路径。

唯一需要注意的是,subversion不会处理二进制差异,因此您的存储库会快速增长,但是如果它成为问题,您可以简单地擦除它并偶尔重新开始。

另一个好处是,您可以获得已部署的每个版本的完整记录。

我已经将这种技术用于多个项目,并希望所有部署系统都更像它:即原子更新,易于回滚,有针对性的单个文件更新,完整的版本历史,......

答案 4 :(得分:1)

以下是我正在发布的内容:

  1. 我有一个关于teamcity的钩子,每次我使用svn进行提交时,它使用rakefile将文件复制到dropbox文件夹,我也有一个git存储库。
  2. 提交/推送已更改的文件(对于此git存储库)。我还在服务器上安装了Dropbox
  3. 将更改从dropbox(使用git)拉到暂存应用程序以再次检查。
  4. 一旦暂存应用程序的一切正常,我就用iis
  5. 中的生产应用程序切换它
  6. 当我想再次发布时,一旦所有内容与dropbox同步,我再次拉动,在之前的制作中,现在变成了舞台制作,我再次切换应用程序。
  7. 结果 - >用户获得0秒停机时间。

    如果你想削减一些角落。您可以直接在生产站点上执行git pull。结果 - >用户停机时间为1 2秒

    如果你真的想要削减一些角落。您可以将Dropbox文件夹直接安装到生产文件夹中,Dropbox将同步所有内容。结果5用户停机时间为6秒或更长时间。

答案 5 :(得分:0)

在build / dev框中,使用命令行MSBuild构建项目的SLN(或wdproj)。确保预先编译所有内容。使用在构建之前清理的单独输出路径。压缩结果,并将其传输到带外的Web服务器(通过UNC路径或FTP服务器,或其他)。在服务器上,解压缩并执行xcopy部署。

要最大限度地缩短传输时间,请使用rsync(适用于Windows的版本),或使用带有最大设置的7-zip来压缩二进制文件。

服务器停机时间最小化,因为它只会从本地磁盘复制到本地磁盘。即使速度很快,IIS应用程序池也会循环使用,以弥补负载均衡器后面需要两台机器,以便您可以在另一台机器处理请求时更新一台机器。 (也许是矫枉过正,使用IIS的网络花园进行调查)

要自动执行此过程,请使用Powershell,或者甚至更简单的方法,使用批处理文件和PSExec来运行远程命令。

答案 6 :(得分:0)

为什么不使用Dropbox?!严重....

警告:我没有经过我的测试,仅仅是一种假设的答案

解决方案1: 以非专业的方式,我会在所有服务器上安装Dropbox,包括登台服务器。只需将Web部署从Visual Studio部署到分段。

Dropbox可以非常快速地同步文件,尤其是当您启用“网络下载”时,文件从本地服务器而不是从Dropbox下载!

解决方案2: 从Visual Studio创建部署包并将其保存到与dropbox同步的本地文件夹。然后创建一个自动运行deploy.cmd的计划任务,并在完成后清除部署文件夹的内容,以避免重复部署。

使用Dropbox的问题

  • ACL不会同步:(
  • 远程桌面会话应始终处于活动状态,因为Dropbox在托盘(非服务)中运行
  • 文件夹不应包含任何已更改的“数据”文件,否则将发生冲突

答案 7 :(得分:-1)

您从VS而不是从构建/持续集成服务器部署的事实是这里的问题。