【问题标题】:How do you deploy your ASP.NET applications to live servers?如何将 ASP.NET 应用程序部署到实时服务器?
【发布时间】:2010-11-11 17:05:05
【问题描述】:

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

我对您的持续集成构建服务器将二进制文件放到某个位置和第一个用户请求命中这些二进制文件之间发生的工作流特别感兴趣。

  1. 您是使用某些特定工具还是仅使用 XCOPY?应用程序是如何打包的(ZIP、MSI、...)?

  2. 第一次部署应用程序时,您如何设置应用程序池和虚拟目录(您是手动创建它们还是使用某些工具创建它们)?

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

  4. 您是否跟踪给定应用程序的所有已部署版本,如果出现问题,您是否有将应用程序恢复到以前已知工作状态的程序?

请随意完成之前的列表。


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

  1. 我们将Web Deployment Project 添加到解决方案并设置它以构建 ASP.NET Web 应用程序
  2. 我们将设置项目(NOT Web 设置项目)添加到解决方案中,并将其设置为获取 Web 部署项目的输出
  3. 我们添加一个自定义安装操作,并在 OnInstall 事件中运行一个自定义构建 .NET 程序集,该程序集使用System.DirectoryServices.DirectoryEntry 在 IIS 中创建一个应用程序池和一个虚拟目录(此任务仅在第一次部署应用程序时执行)。我们支持 IIS 中的多个网站、虚拟目录的身份验证和应用程序池的设置身份。
  4. 我们在 TFS 中添加了一个自定义任务来构建安装项目(TFS 不支持安装项目,因此我们必须使用 devenv.exe 来构建 MSI)
  5. MSI 安装在实时服务器上(如果有以前版本的 MSI,则首先将其卸载)

【问题讨论】:

标签: asp.net deployment


【解决方案1】:

网络设置/安装项目 - 如果出现问题,您可以轻松卸载它

【讨论】:

    【解决方案2】:

    我们使用 Setup Factory 将所有代码部署在 MSI 中。如果必须更改某些内容,我们将重新部署整个解决方案。这对于 css 文件来说听起来有点过头了,但它绝对可以让所有环境保持同步,而且我们确切地知道生产中的内容(我们以相同的方式部署到所有测试和 uat 环境)。

    【讨论】:

      【解决方案3】:

      早在 2009 年,我们就使用 CruiseControl.net 来构建我们的持续集成版本,并输出发布媒体。

      从那里我们使用Smart Sync software 与不在负载平衡池中的生产服务器进行比较,并将更改上移。

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

      【讨论】:

      • 听起来更像是广告而不是答案
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我们对实时服务器进行滚动部署,因此我们不使用安装程序项目;我们有更像 CI 的东西:

        • “实时”构建服务器从 已批准 源(不是 repo 的“HEAD”)构建
        • (备份后;-p)
        • robocopy 发布到临时服务器(“实时”,但不在 F5 集群中)
        • 在登台服务器上完成最终验证,通常使用“主机”黑客来尽可能接近地模拟整个事情
        • robocopy /L 用于在下一次“推送”中自动分发更改列表,以提醒任何错误
        • 作为计划过程的一部分,集群会循环,通过 robocopy 部署到集群中的节点(当它们不在集群中时)

        robocopy 自动确保只部署更改。

        重新应用程序池等;我希望 喜欢 这是自动化的 (see this question),但目前 此刻 它是手动的。不过,我真的很想改变这一点。

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

        【讨论】:

        • 你们如何处理approved 源?分支机构?
        • @Shawn 我必须强调这是前世的一份工作——很久以前。我什至不记得当时的确切过程。可能基本上是“不要搞砸”。
        【解决方案6】:

        回答您的问题:

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

        到目前为止,保持美观和简单已经为我们省去了很多麻烦。

        【讨论】:

          【解决方案7】:

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

          • 我使用源代码存储库(如 Subversion)
          • 在服务器上,我有一个执行以下操作的 bash 脚本:
            • 查看最新代码
            • 进行构建(创建 DLL)
            • 将文件过滤到基本要素(例如删除代码文件)
            • 备份数据库
            • 将文件部署到以当前日期命名的目录中的 Web 服务器
            • 如果部署中包含新架构,则更新数据库
            • 将新安装设为默认安装,以便下次点击时提供该安装

          Checkout 是使用 Subversion 的命令行版本完成的,而构建是使用 xbuild 完成的(与 Mono 项目中的 msbuild 工作类似)。大多数魔法都是在 ReleaseIt 中完成的。

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

          在生产中,我必须输入“deploy”两次:一次用于签出、构建和部署到一个过时的目录,一次用于将该目录设置为默认实例。由于目录已过时,我只需在相关目录中键入“deploy”即可恢复到任何以前的部署。

          初始部署需要几分钟,恢复到以前的版本需要几秒钟。

          这对我来说是一个不错的解决方案,并且仅依赖于三个命令行实用程序(svn、xbuild 和 releaseit)、DB 客户端、SSH 和 Bash。

          我真的需要在某个时候更新 CodePlex 上的 ReleaseIt 副本:

          http://releaseit.codeplex.com/

          【讨论】:

            【解决方案8】:

            网站

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

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

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

            数据库

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

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

            【讨论】:

            • 如果您没有对目标数据库的网络访问权限,您可以让有权使用免费工具 SQL Snapper 的人员获取架构快照并将其通过电子邮件发送给您。有了这个,您可以使用 SQL Compare 生成一个同步脚本,然后您可以通过电子邮件将其发回以在远程站点上运行。
            【解决方案9】:

            Unfold 是我为 .net 应用程序编写的类似 capistrano 的部署解决方案。这是我们在所有项目中使用的,它是一个非常灵活的解决方案。它解决了 .net 应用程序的大部分典型问题,如 Rob Conery 在this blog post 中所述。

            • 它具有良好的“默认”行为,从某种意义上说,它为您做了很多标准的事情:从源代码管理中获取代码、构建、创建应用程序池、设置 IIS 等
            • 基于源代码管理中的内容发布
            • 它具有任务挂钩,因此可以轻松扩展或更改默认行为
            • 它有回滚
            • 都是powershell,所以没有任何外部依赖
            • 它使用 powershell 远程处理来访问远程机器

            这是introduction 和其他一些博文。

            所以回答上面的问题:

            • 应用程序是如何打包的(ZIP、MSI、...)?

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

            • 第一次部署应用程序时,您如何设置应用程序池和虚拟目录(您是手动创建它们还是使用某些工具创建它们)?

              Unfold 使用 Powershell 的 WebAdministration Module 配置应用程序池和网站应用程序。它允许我们(和您)修改应用程序池或网站的任何方面

            • 当静态资源发生变化(CSS、JS 或图像文件)时,您是重新部署整个应用程序还是仅重新部署修改后的资源?当程序集/ASPX 页面发生变化时如何?

              是的,展开是这样做的,任何部署都安装在其他部署旁边。这样我们就可以轻松回滚 当出现问题时。它还允许我们轻松追溯已部署的版本 源代码控制修订。

            • 您是否跟踪给定应用程序的所有已部署版本?

              是的,展开会保留旧版本。不是所有版本,而是多个版本。它使回滚几乎变得微不足道。

            【讨论】:

            • 很好,但需要从目标机器访问存储库。
            【解决方案10】:

            您是使用某些特定工具还是仅使用 XCOPY?应用程序是如何打包的(ZIP、MSI、...)?

            作为BuildMaster的开发者,这自然是我用的。所有应用程序都作为工件在工具中构建和打包,在内部存储为 ZIP 文件。

            第一次部署应用程序时,您如何设置应用程序池和虚拟目录(您是手动创建它们还是使用某些工具创建它们)?

            手动 - 我们在工具中创建了一个变更控制,当应用程序在其测试环境中移动时,它会提醒我们在未来环境中执行的确切步骤。这也可以通过简单的 PowerShell 脚本自动完成,但我们不会经常添加新应用程序,因此只需花费 1 分钟手动创建站点即可。

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

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

            您是否跟踪给定应用程序的所有部署版本,如果出现问题,您是否有将应用程序恢复到以前已知工作状态的程序?

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

            【讨论】:

              【解决方案11】:

              在我工作的最后一家公司,我们曾经使用 rSync 批处理文件进行部署,以仅上传自上次上传以来的更改。 rSync 的美妙之处在于您可以添加排除列表以排除特定文件或文件名模式。例如,排除我们所有的 .cs 文件、解决方案和项目文件真的很容易。

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

              • 首先,检查用户是否拥有最新版本。如果没有,请提示他们更新或立即运行更新。
              • 从服务器下载一个名为“synclog.txt”的文本文件,其中详细说明了 SVN 用户是谁、他们上传的修订号以及上传的日期和时间。为当前上传添加一个新行,然后将其与更改的文件一起发送回服务器。这样一来,在上传引起问题的情况下,可以非常轻松地找出要回滚到的网站版本。

              除此之外,还有第二个批处理文件,它只检查实时服务器上的文件差异。这可以突出一个常见的问题,即有人会上传但没有将他们的更改提交到 SVN。结合上面提到的同步日志,我们可以找出可能的罪魁祸首是谁,并要求他们提交工作。

              最后,rSync 允许您备份在上传期间被替换的文件。我们已经将它们移动到备份文件夹中。因此,如果您突然意识到某些文件不应该被覆盖,您可以在该文件夹中找到每个文件的最后备份版本。

              虽然当时该解决方案感觉有点笨拙,但当我在上传方法不太优雅或简单的环境中工作时(远程桌面、复制和粘贴整个网站、例如)。

              【讨论】:

                【解决方案12】:

                在过去的一年里,我们一直在改进我们的发布流程,现在我们已经成功了。我正在使用 Jenkins 来管理我们所有的自动化构建和发布,但我相信您可以使用 TeamCity 或 CruiseControl。

                因此,在签入时,我们的“正常”构建会执行以下操作:

                • Jenkins 执行 SVN 更新以获取最新版本的代码
                • 已针对我们自己的本地 NuGet 存储库运行 NuGet 包还原
                • 应用程序是使用 MsBuild 编译的。设置它是一次冒险,因为您需要安装正确的 MsBuild,然后在您的构建框上安装 ASP.NET 和 MVC dll。 (附带说明,当我在 .csproj 文件中输入 <MvcBuildViews>true</MvcBuildViews> 以编译视图时,msbuild 随机崩溃,所以我不得不禁用它)
                • 编译代码后,将运行单元测试(我为此使用了 nunit,但你可以使用任何你想要的东西)
                • 如果所有单元测试都通过,我会停止 IIS 应用程序池,在本地部署应用程序(只需几个基本的 XCOPY 命令复制必要的文件),然后重新启动 IIS(我遇到了 IIS 锁定文件的问题,这解决了它)
                • 每个环境都有单独的 web.config 文件;开发,uat,产品。 (我尝试使用网络转换的东西,但收效甚微)。所以正确的 web.config 文件也被复制了
                • 然后我使用 PhantomJS 执行一堆 UI 测试。它还以不同的分辨率(移动设备、桌面)截取一堆屏幕截图,并在每个屏幕截图上标记一些信息(页面标题、分辨率)。 Jenkins 为处理这些屏幕截图提供了强大的支持,它们被保存为构建的一部分
                • 集成 UI 测试通过后,构建成功

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

                • 如果最后一次构建成功,Jenkins 会进行另一次 SVN 更新
                • 应用程序是使用 RELEASE 配置编译的
                • 创建了一个“www”目录并将应用程序复制到其中
                • 然后我使用 winscp 在构建框和 UAT 之间同步文件系统
                • 我向 UAT 服务器发送了一个 HTTP 请求,并确保我收到了 200
                • 此修订在 SVN 中标记为 UAT-datetime
                • 如果我们已经走到这一步,构建成功!

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

                • 用户选择了一个之前创建的 UAT 标签
                • 标签被“切换”到
                • 代码已编译并与 Prod 服务器同步
                • 对 Prod 服务器的 Http 请求
                • 此修订在 SVN 中标记为 Prod-datetime
                • 版本已压缩并存储

                一个完整的构建到生产大约需要 30 秒,我对此非常非常满意。

                此解决方案的优点:

                • 很快
                • 单元测试应该捕获逻辑错误
                • 当 UI 错误投入生产时,屏幕截图有望显示是哪个版本号导致该错误
                • UAT 和 Prod 保持同步
                • Jenkins 向您展示了 UAT 和 Prod 的出色发布历史以及所有提交消息
                • UAT 和 Prod 版本均自动标记
                • 您可以查看发布的时间和发布者

                此解决方案的主要缺点是:

                • 每当您发布到 Prod 时,您都需要发布到 UAT。这是我们做出的一个有意识的决定,因为我们希望始终确保 UAT 始终与 Prod 保持同步。不过,这很痛苦。
                • 有很多配置文件四处飘荡。我试图在 Jenkins 中拥有这一切,但在此过程中需要一些支持批处理文件。 (这些也已签入)。
                • 数据库升级和降级脚本是应用程序的一部分,并在应用程序启动时运行。它(大部分)有效,但很痛苦。

                我很想听听任何其他可能的改进!

                【讨论】:

                  【解决方案13】:

                  我建议不要仅仅覆盖现有的应用程序文件,而是为每个版本创建一个目录并将 IIS 应用程序重新指向新路径。 这有几个好处:

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

                  我们遇到的唯一问题是,如果您不重新启动应用程序池并依赖自动应用程序域切换,资源会被缓存。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-31
                    • 1970-01-01
                    • 1970-01-01
                    • 2014-07-08
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多