【问题标题】:Publishing an ASP.NET MVC2 site with Web Deploy使用 Web Deploy 发布 ASP.NET MVC2 站点
【发布时间】:2011-06-20 14:03:06
【问题描述】:

我目前使用 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 个更改的文件。这种情况很荒谬,是我们网站目前最大的弱点之一。所以我开始了一个体面的赏金计划,希望能解决这个问题。

还有一些问题可能会导致解决方案:

  • 为什么只更改了几个文件就需要这么长时间?
  • 为什么网络部署 zip 总是包含整个代码库,而不仅仅是更改的文件?
  • 为什么我不自己手动复制更改的文件并跳过整个 Web 部署?但是很难手动计算出哪些文件发生了变化。我使用 SVN - 它有没有办法只输出在两个分支之间发生变化的文件?
  • 还有哪些我还没有想到的问题?

回复答案:

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

我确实可以完全控制服务器,并且它确实支持 Web 部署。实际上有 2 台服务器:主要的实时服务器,以及我们准备好的冗余服务器,以防第一台服务器发生故障。因此,任何解决方案都必须易于部署到多台服务器(网络部署在它停止工作之前是理想的)。

建议为每个版本创建一个新文件夹,然后仅将 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。

【问题讨论】:

  • 是什么导致部署增长 - 代码或内容,例如图片?
  • 代码库非常大,但自网站首次启动以来并没有显着增长,现在可能增长了 10 - 20%。网络部署 zip 文件约为 15mb。
  • Web 部署需要大约 30 秒才能到达登台服务器(位于开发箱旁边),但相同的部署需要很长时间才能到达实时服务器(托管公司数据中心的 vps)。
  • 那太糟糕了。我不知道赏金在赏金期到期的同一秒自动授予。一点宽限期会很好。

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


【解决方案1】:

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

  • 网络服务器是属于域还是工作组?
  • dcdiag 显示什么?
  • netdiag 显示什么?
  • 开发盒和产品盒在同一个域中吗?

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

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

HTH, -埃里克

【讨论】:

  • +1 小岛屿发展中国家建议;当域控制器不可用时,我已经让我自己的机器变慢了
【解决方案2】:

我会首先尝试找出发生超时的位置。您提到了一个包含 2,500 个文件的 15MB zip,我觉得这并没有特别大。您是否尝试过在 Visual Studio 中创建部署包,然后直接在服务器上运行它?这将消除网络延迟,这是一个非常基本的超时变量。

至于为什么需要上传包含整个应用程序的 zip 文件,您需要记住更改的实际标识以及随后部署到 IIS 中的所有操作都发生在服务器上。这不是你本地机器上的 Visual Studio 或 msdeploy 做主。

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

尝试直接从 SVN 进行更改也是有风险的。您的第一个问题是,如果您要发布适当的更改,您需要完全相信您正在更新的修订版的完整性和准确性。。然后,您将尝试将这些同步到目标,并且您又回到了上一段中提出的相同问题。另一个大问题是版本控制目标代码总是很讨厌。您将永远与项目中的其他任何人发生冲突,而 VCS 根本不打算以这种方式运行。

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

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

【讨论】:

  • 是的,我现在手动将部署复制到 Web 服务器并在那里运行 - 我必须这样做,因为右键单击部署不再起作用。上次手动复制并使用“部署|导入”菜单cmd在服务器上手动运行后花了18分钟。而且,是的,我使用发布转换来更改 web.config,以便它具有实时站点的正确信息。
  • 是的,同意手动复制或手动 SVN 结帐是非常危险的。我更喜欢解决 Web 部署问题的解决方案,而不是用不可避免会出错的手动过程替换它。
  • 我需要再过几个小时再发布一次:我可以在 Web 服务器上做些什么来看看为什么需要这么长时间? IIS 部署 |导入只显示一个带有进度条的对话框 - 是否在任何地方记录了任何内容?
  • 您是否尝试过将相同的包部署到另一台服务器?甚至到您的本地机器?如果您想聊天,请在 Twitter 或电子邮件(博客链接)上联系我,这可能需要一段时间。
  • 在 3 台服务器上进行时间测试: 1. 登台服务器 + 登台部署包 = 5 秒。 2. 登台服务器 + 实时部署 = 20 秒。 3. 冗余服务器 + 登台部署 = 1 小时 20 (!) 4. 冗余服务器 + 实时部署 = 超过 1 小时 20 小时。 6. 实时服务器 + 实时部署包 - 6 分钟(是的,这次要快得多)
【解决方案3】:

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

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

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

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

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

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

另一个优点是您对曾经部署的每个版本都有完整的记录。

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

【讨论】:

    【解决方案4】:

    这是我的发布方式:

    1. 我在 teamcity 上有一个钩子,每次我使用 svn 进行提交时,它都会使用 rakefile 将文件复制到我也有一个 git 存储库的 Dropbox 文件夹。
    2. 对已更改的文件执行提交/推送(对于此 git 存储库)。我还在服务器上安装了保管箱
    3. 将更改从 Dropbox(使用 git)拉到暂存应用程序以再次检查。
    4. 一旦暂存应用程序一切正常,我将其切换为来自 iis 的生产应用程序
    5. 当我想再次发布时,一旦所有内容都与 Dropbox 同步,我会再次拉取之前的产品(现在成为暂存产品),然后再次切换应用程序。

    结果->用户的停机时间为 0 秒。

    如果你想偷工减料。您可以直接在生产站点上执行 git pull。结果->1 2 秒的用户停机时间

    如果你真的想偷工减料。您可以将保管箱文件夹直接安装到您的生产文件夹中,保管箱将同步所有内容。结果 5 用户的停机时间为 6 秒或更长时间。

    【讨论】:

      【解决方案5】:

      我刚刚遇到了一个类似的问题,即 webdeploy 开始需要很长时间,尤其是当它到达 "Updating setAcl" 时。我不愿意像以前的一些答案所建议的那样禁用更新 ACL,尤其是当它可以很好地将同一个项目部署到不同的服务器时。

      所以我查看了两台目标机器之间的不同之处,事后看来,解决方案非常明显。在生产机器上,我们有很多临时本地文件被创建并存储了一个月(按设计)。我减少了文件数量,发布时间从 30 分钟缩短到了 15 秒左右。

      【讨论】:

        【解决方案6】:

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

        但在共享主机上,这将无法正常工作。也许有一些方法可以通过上传代码然后重命名文件夹以使其指向新文件来适应相同的策略。

        无论如何,网络部署似乎应该支持仅发送更改的内容。但我认为在这种情况下您的主机需要支持 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 推送更改。

        【讨论】:

        • troyhunt.com/2010/11/you-deploying-it-wrong-teamcity_24.html 正是我的做法......直到它开始超时
        • 主机支持web部署,其IIS7
        • 部署日志显示,花费这么长时间的是部署的设置 ACL 部分。其他一切都运行得非常快。
        • 是否需要它来设置ACL?如果没有,您可以尝试禁用它:orcsweb.com/blog/rick/…
        • @Mikael 感谢您的链接,我已经关闭了设置 ACL,并将在几个小时内发布。我们很快就会看到情况如何!
        【解决方案7】:

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

        要尽量减少传输时间,请使用 rsync(有适用于 Windows 的版本),或使用 7-zip 以最大设置压缩二进制文件。

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

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

        【讨论】:

        • 您不想确保没有当前线程正在访问您的文件吗? xcopy 不执行重试(尽管 robocopy 执行),但即便如此,也只会减轻 影响,而不是 原因;您可能希望回收应用程序池,并且恕我直言,任何以这种方式作用于并发访问的文件的工具(我不知道 MSDeploy 是否这样做)都应该使用事务性 ntfs。
        • 有趣的亨利克。自从 COM+ 之前的 MTS 过去以来,我还没有听说过事务性 NTFS。我怀疑 MSDeploy 使用这个,任何专家?关于锁定,是的,安全的方法是通过 IIS API(甚至 IIS 本身,在我提到的负载均衡器场景中)关闭应用程序池,然后使用 Robocopy 进行文件复制,然后再次启动应用程序池。但事情并没有那么简单。
        • 您可以将 Web 项目部署到 ZIP 包并使用 msdeploy.exe 将其发布到服务器。
        【解决方案8】:

        为什么不使用 Dropbox?!说真的……

        警告:这还没有经过我的测试,只是一个假设的答案

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

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

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

        使用 Dropbox 的问题

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

        【讨论】:

          【解决方案9】:

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

          【讨论】:

          • 为什么会出现这个问题?如果没有某种解释,答案就没有用或没有帮助......
          猜你喜欢
          • 2011-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-16
          • 2011-11-28
          相关资源
          最近更新 更多