设置 Azure 应用服务中的过渡环境

将 Web 应用、Linux 上的 Web 应用、移动后端或 API 应用部署到 Azure 应用服务时,如果应用在“标准”、“高级”或“隔离”应用服务计划层中运行,则可以使用单独的部署槽,而不是默认的生产槽。 部署槽是具有自身主机名的实时应用。 两个部署槽(包括生产槽)之间的应用内容与配置元素可以交换。

将应用程序部署到非生产槽具有以下优点:

  • 可以在与生产槽交换前,在分阶段部署槽中验证应用更改。
  • 首先将应用部署到槽,然后将其交换到生产,这确保槽的所有实例都已准备好,然后交换到生产。 部署应用时,这样可避免停机。 流量重定向是无缝的,且不会因交换操作而删除任何请求。 当不需要预交换验证时,可以通过配置自动交换来自动化这整个工作流。
  • 交换后,具有以前分阶段应用的槽现在具有以前的生产应用。 如果交换到生产槽的更改与预期不同,可以立即执行同一交换来收回“上一已知的良好站点”。

每种应用服务计划层支持不同数量的部署槽。 使用部署槽位不会产生额外的费用。 若要了解应用层支持的槽数,请参阅应用服务限制

若要将应用缩放到其他层,请确保目标层支持应用业已使用的槽数。 例如,如果应用有 5 个以上的槽,则不能向下缩放到“标准”层,因为“标准”层只支持 5 个部署槽 。

先决条件

有关执行所需槽操作所需的权限的信息,请参阅资源提供程序操作(例如,搜索)。

添加槽

应用必须在“标准”、“高级”或“独立”层中运行,才能启用多个部署槽位 。

  1. Azure 门户中,导航到应用的管理页。

  2. 在左窗格中,选择“部署槽”>“添加槽” 。

    注意

    如果应用尚未处于“标准”、“高级”或“独立”层中,请选择“升级”并转到应用的“缩放”选项卡,然后继续操作。

  3. 在“添加槽”对话框中,为槽提供一个名称,并选择是否要从其他部署槽中克隆应用配置。 选择“添加”以继续。

    A screenshot that shows how to configure a new deployment slot called 'staging' in the portal.

    可以从任何现有槽克隆配置。 可以克隆的设置包括应用设置、连接字符串、语言框架版本、Web 套接字、HTTP 版本和平台位数。

    注意

    目前,专用终结点不能跨槽克隆。

  4. 添加槽后,选择“关闭”以关闭对话框。 新槽现在显示在“部署槽”页面中。 默认情况下,新槽的“流量 %”设置为 0,所有客户流量都路由到生产槽。

  5. 选择新部署槽打开该槽的资源页。

    A screenshot that shows how to open deployment slot's management page in the portal.

    过渡槽具有管理页面,就像任何其他应用服务应用一样。 可以更改此槽的配置。 为了提醒你正在查看的是部署槽,应用名称会显示为“<app-name>/<slot-name>”,应用类型为“应用服务(槽)”。 也可以将槽视为资源组中具有相同名称的单独应用。

  6. 选择此槽资源页中的应用 URL。 部署槽有其自己的主机名,同时也是动态应用。 若要限制对部署槽的公共访问权限,请参阅 Azure 应用服务 IP 限制

即使从其他槽克隆设置,新部署槽位也无内容。 例如,可以使用 Git 发布到此槽。 可以从其他存储库分支或不同的存储库部署到槽。 从 Azure 应用服务获取发布配置文件可以提供部署到槽所需的信息。 可通过 Visual Studio 导入配置文件,以将内容部署到槽。

槽的 URL 格式为 http://sitename-slotname.chinacloudsites.cn。 为了保证 URL 长度不超过必要的 DNS 限制范围,站点名称将被截断为 40 个字符,并且站点名和槽名的组合必须少于 59 个字符。

交换期间发生的情况

交换操作步骤

交换两个槽时(通常是从作为源的过渡槽交换到作为目标的生产槽),应用服务将执行以下操作,以确保目标槽不会出现停机:

  1. 将目标槽(例如生产槽)中的以下设置应用到源槽的所有实例:

    出现其中的任何情况都会触发源槽中所有实例的重启。 在交换并预览期间,这标志着第一阶段结束。 交换操作将会暂停,你可以使用目标槽的设置验证源槽是否正常工作。

  2. 等待源槽中的每个实例完成重启。 如果有任何实例无法重启,交换操作将会还原对源槽所做的所有更改,并停止操作。

  3. 如果启用了本地缓存,则会通过对每个源槽实例上的应用程序根 ("/") 发出 HTTP 请求,来触发本地缓存初始化。 等到每个实例返回了任何 HTTP 响应。 本地缓存初始化会导致每个实例再次重启。

  4. 如果结合自定义预热启用了自动交换,则会通过对每个源槽实例上的应用程序根 ("/") 发出 HTTP 请求,来触发应用程序初始化

    如果未指定 applicationInitialization,则向每个实例上的源槽的应用程序根触发 HTTP 请求。

    如果某个实例返回了任何 HTTP 响应,则认为该实例已预热。

  5. 如果源槽上的所有实例已成功预热,则通过交换两个槽的路由规则来交换这两个槽。 完成此步骤后,目标槽(例如生产槽)包含先前已在源槽中预热的应用。

  6. 源槽包含先前位于目标槽中的预交换应用后,通过应用所有设置并重启实例来执行相同的操作。

在执行交换操作期间的任何时候,初始化已交换应用的所有工作都在源槽上发生。 准备和预热源槽时,目标槽将保持联机,而不管交换是成功还是失败。 若要将过渡槽与生产槽交换,请确保生产槽始终是目标槽。 这样,交换操作才不会影响生产应用。

注意

在交换过程的最后一步中,会快速回收先前生产实例中的实例(即交换操作之后将交换到临时过程的实例)。 如果应用程序中存在任何长期运行的操作,则在辅助角色回收时,这些操作会被放弃。 这同样适用于函数应用。 因此,应采用容错方式编写应用程序代码。

交换哪些设置?

从另一个部署槽克隆配置时,可以编辑克隆的配置。 某些配置元素在交换时遵循内容(不特定于槽),而其他配置元素会在交换之后保留在同一个槽(特定于槽)。 以下列表显示交换槽时会更改的设置。

已交换的设置

  • 常规设置 - 例如 Framework 版本、32/64 位、Web 套接字
  • 应用设置(可以配置为停在槽中)
  • 连接字符串(可以配置为停在槽中)
  • 处理程序映射
  • 公用证书
  • WebJobs 内容
  • 混合连接 *
  • 服务终结点 *
  • Azure 内容分发网络 *

标有星号 (*) 的功能计划取消交换。

不交换的设置

  • 发布终结点
  • 自定义域名
  • 非公共证书和 TLS/SSL 设置
  • 缩放设置
  • Web 作业计划程序
  • IP 限制
  • Always On
  • 诊断设置
  • 跨域资源共享 (CORS)
  • 虚拟网络集成
  • 路径映射
  • 以后缀 _EXTENSION_VERSION 结尾的设置

注意

若要使这些设置可交换,请在应用的每个槽中添加应用设置 WEBSITE_OVERRIDE_PRESERVE_DEFAULT_STICKY_SLOT_SETTINGS,并将其值设置为 0false。 这些设置要么全部可交换,要么根本不可交换。 不能仅使某些设置可交换,而使其他设置不可交换。

应用于不交换的设置的某些应用设置也不交换。 例如,由于诊断设置不会交换,因此相关的应用设置(如 WEBSITE_HTTPLOGGING_RETENTION_DAYSDIAGNOSTICS_AZUREBLOBRETENTIONDAYS)也不会交换,即使它们未显示为槽设置也是如此。

若要将应用设置或连接字符串配置为粘滞到特定的槽(未交换),请转到该槽的“配置”页。 添加或编辑某个设置,然后选择“部署槽设置”。 选中此复选框可让应用服务知道该设置不可交换。

A screenshot that shows how to configure an app setting as a slot setting in the Azure portal.

交换两个槽

可以在应用的“部署槽”页上以及“概述”页上交换部署槽 。 有关交换槽的技术详细信息,请参阅交换期间发生的情况

重要

将应用从部署槽交换到生产槽之前,请确保生产槽是目标槽,并且已完全根据生产槽中的情况配置了源槽中的所有设置。

若要交换部署槽:

  1. 转到应用的“部署槽”页,然后选择“交换”。

    A screenshot that shows how to initiate a swap operation in the portal.

    “交换”对话框显示将要更改的所选源和目标槽中的设置。

  2. 选择所需的“源”和“目标”槽 。 目标通常是生产槽。 此外,选择“源更改”和“目标更改”选项卡,并验证配置更改是否符合预期 。 完成后,可以通过选择“交换”立即交换槽。

    A screenshot that shows how to configure and complete a swap in the portal.

    若要在交换实际发生之前查看目标槽如何使用新设置运行,请不要选择“交换”,而是按照交换预览中的说明进行操作。

  3. 完成后,选择“关闭”以关闭对话框。

如果遇到任何问题,请参阅排查交换问题

带预览的交换(多阶段交换)

在交换到用作目标槽的生产槽之前,请使用交换的设置验证应用的运行。 源槽在交换完成之前也已预热,这对于任务关键型应用程序是可行的。

在执行交换并预览时,应用服务将执行相同的交换操作,但完成第一个步骤后会暂停。 然后,你可以在完成交换之前验证过渡槽中的结果。

如果取消交换,应用服务会重新将配置元素应用到源槽。

注意

如果其中一个槽已启用站点身份验证,则无法使用预览版交换。

若要交换并预览:

  1. 按照交换部署槽中的步骤进行操作,但请选择“使用带预览的交换”。

    A screenshot that shows how to configure a swap with preview in the portal.

    该对话框显示源槽中的配置在阶段 1 中的更改方式,以及源槽和目标槽在阶段 2 中的更改方式。

  2. 如果已准备好开始交换,请选择“开始交换”。

    第 1 阶段完成后,对话框中会显示通知。 通过转到 https://<app_name>-<source-slot-name>.chinacloudsites.cn 来预览源槽中的交换。

  3. 准备完成挂起的交换后,在“交换操作”中选择“完成交换”,然后选择“完成交换” 。

    若要取消挂起的交换,请改为选择“取消交换”,然后选择底部的“取消交换”。

  4. 完成后,选择“关闭”以关闭对话框。

如果遇到任何问题,请参阅排查交换问题

回滚交换

如果在槽交换后目标槽(例如,生产槽)中发生任何错误,请通过立即交换相同的两个槽以将槽恢复到其交换前状态。

配置自动交换

注意

Linux 上的 Web 应用和用于容器的 Web 应用不支持自动交换。

自动交换简化了 Azure DevOps 方案,在此方案中,可连续部署应用,无需冷启动且不会给应用的客户造成停机。 启用从某个槽到生产槽的自动交换后,每次将代码更改推送到该槽时,应用服务会在源槽中预热后自动将应用交换到生产槽中。

注意

在为生产槽配置自动交换之前,请考虑在非生产目标槽上测试自动交换。

若要配置自动交换:

  1. 转到应用的资源页。 选择“部署槽”>“<所需的源槽>”>“配置”>“常规设置”。

  2. 对于“启用自动交换”,请选择“打开”。 为“自动交换部署槽”选择所需的目标槽,然后选择在命令栏上“保存”。

    A screenshot that shows how to configure auto swap into the production slot in the portal.

  3. 执行代码推送到源槽。 片刻之后,自动交换就会发生,而更新将反映在目标槽的 URL 上。

如果遇到任何问题,请参阅排查交换问题

指定自定义预热

某些应用在交换之前可能需要执行自定义的预热操作。 web.config 中的 applicationInitialization 配置元素可用于指定自定义初始化操作。 交换操作在与目标槽交换之前等待此自定义预热操作完成。 以下是 web.config 片段的示例。

<system.webServer>
    <applicationInitialization>
        <add initializationPage="/" hostName="[app hostname]" />
        <add initializationPage="/Home/About" hostName="[app hostname]" />
    </applicationInitialization>
</system.webServer>

有关自定义 applicationInitialization 元素的详细信息,请参阅最常见的部署槽位交换故障以及如何修复它们

还可以使用以下一项或两项应用设置来自定义预热行为:

  • WEBSITE_SWAP_WARMUP_PING_PATH:通过 HTTP 执行 ping 操作来预热站点的路径。 通过指定以斜杠开头的自定义路径作为值来添加此应用设置。 例如 /statuscheck。 默认值为 /
  • WEBSITE_SWAP_WARMUP_PING_STATUSES:预热操作的有效 HTTP 响应代码。 使用以逗号分隔的 HTTP 代码列表添加此应用设置。 例如 200,202。 如果返回的状态代码不在列表中,则预热和交换操作会停止。 默认情况下,所有响应代码都是有效的。
  • WEBSITE_WARMUP_PATH:站点上的一个相对路径,当站点重启时(不仅仅是在槽交换期间)应该对其进行 ping 操作。 示例值包括 /statuscheck 或根路径 /

注意

每次启动应用都需要运行 <applicationInitialization> 配置元素,而两个预热行为应用设置仅适用于槽交换。

如果遇到任何问题,请参阅排查交换问题

监视交换

如果交换操作需要很长时间才能完成,则可以在活动日志中获取有关交换操作的信息。

在门户的应用资源页上的左窗格中,选择“活动日志”。

交换操作在日志查询中显示为 Swap Web App Slots。 可以将其展开,然后选择一个子操作或错误来查看详细信息。

自动路由生产流量

默认情况下,应用生产 URL (http://<app_name>.chinacloudsites.cn) 的所有客户端请求都将路由到生产槽。 可以将部分流量路由到另一个槽。 如果需要用户对新更新的反馈,但是还没有准备好将其发布到生产环境中,那么这个功能非常有用。

若要自动路由生产流量:

  1. 转到应用的资源页,然后选择“部署槽”。

  2. 在要路由到的槽的“流量 %”列中,指定一个百分比(介于 0 到 100 之间)以表示要路由的总流量。 选择“保存”。

    A screenshot that shows how to route a percentage of request traffic to a deployment slot, in the portal.

保存设置后,指定百分比的客户端将随机路由到非生产槽。

客户端在自动路由到特定槽后,会被“固定”到该槽一小时或直到 Cookie 被删除为止。 在客户端浏览器上,可以通过查看 HTTP 标头中的 x-ms-routing-name cookie 来查看会话固定到哪个槽。 路由到“暂存”槽的请求具有 cookie x-ms-routing-name=staging。 路由到生产槽的请求具有 cookie x-ms-routing-name=self

手动路由生产流量

除了自动流量路由以外,应用服务也可以将请求路由到特定槽。 如果想要让用户能够选择加入或退出 beta 应用,这就非常有用。 若要手动路由生产流量,请使用 x-ms-routing-name 查询参数。

例如,若要让用户选择退出 beta 应用,可以在网页中插入以下链接:

<a href="<webappname>.chinacloudsites.cn/?x-ms-routing-name=self">Go back to production app</a>

字符串 x-ms-routing-name=self 指定生产槽位。 在客户端浏览器访问该链接后,它将重定向到生产槽。 每个后续请求包含一个用于将会话固定到生产槽的 x-ms-routing-name=self Cookie。

若要让用户选择加入 beta 应用,请将相同的查询参数设置为非生产槽的名称。 下面是一个示例:

<webappname>.chinacloudsites.cn/?x-ms-routing-name=staging

默认情况下,为新槽提供 0% 的路由规则(以灰色显示)。 将此值显式设置为 0% 时(以黑色文本显示),用户可以使用 x-ms-routing-name 查询参数手动访问过渡槽。 但是,他们不会自动路由到该槽,因为路由百分比设置为 0。 这是一种高级方案,在其中可以对公众“隐藏”过渡槽,同时允许内部团队测试槽中的更改。

删除槽

搜索并选择应用。 选择“部署槽”>“<删除槽>”>“概述”。 应用类型将显示为“应用服务(槽)”,以提醒你正在查看部署槽。 在删除某个槽之前,请确保停止该槽并将该槽中的流量设置为零。 在命令栏上选择“删除”。

A screenshot that shows how to delete a deployment slot in the portal.

使用资源管理器模板自动执行

Azure 资源管理器模板是用于自动部署和配置 Azure 资源的声明性 JSON 文件。 若要使用资源管理器模板交换槽,请在 Microsoft.Web/sites/slotsMicrosoft.Web/sites 资源中设置两个属性:

  • buildVersion:这是一个字符串属性,表示槽中部署的应用的当前版本。 例如:“v1”、“1.0.0.1”或“2019-09-20T11:53:25.2887393-07:00”。
  • targetBuildVersion:这是一个字符串属性,指定槽应使用哪个 buildVersion。 如果 targetBuildVersion 与当前 buildVersion 不相等,它将通过查找具有指定 buildVersion 的槽来触发交换操作。

示例资源管理器模板

以下资源管理器模板通过更新 staging 槽的 buildVersion 并在生产槽上设置 targetBuildVersion 来交换两个槽。 它假定你已创建一个名为 staging 的槽。

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "my_site_name": {
            "defaultValue": "SwapAPIDemo",
            "type": "String"
        },
        "sites_buildVersion": {
            "defaultValue": "v1",
            "type": "String"
        }
    },
    "resources": [
        {
            "type": "Microsoft.Web/sites/slots",
            "apiVersion": "2018-02-01",
            "name": "[concat(parameters('my_site_name'), '/staging')]",
            "location": "China East 2",
            "kind": "app",
            "properties": {
                "buildVersion": "[parameters('sites_buildVersion')]"
            }
        },
        {
            "type": "Microsoft.Web/sites",
            "apiVersion": "2018-02-01",
            "name": "[parameters('my_site_name')]",
            "location": "China East 2",
            "kind": "app",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites/slots', parameters('my_site_name'), 'staging')]"
            ],
            "properties": {
                "targetBuildVersion": "[parameters('sites_buildVersion')]"
            }
        }        
    ]
}

此资源管理器模板是幂等的,这意味着,它可以重复执行,并生成相同的槽状态。 如果不对模板进行任何更改,同一模板的后续运行不会触发任何槽交换,因为这些槽已处于所需状态。

排查交换问题

如果在交换槽的过程中出现任何错误,该错误会记录在 D:\home\LogFiles\eventlog.xml 中。 特定于应用程序的错误日志中也会记录该错误。

下面是一些常见的交换错误:

  • 对应用程序根发出的 HTTP 请求已超时。 交换操作将为每个 HTTP 请求等待 90 秒,并最多重试 5 次。 如果所有重试均超时,则表示交换操作已停止。

  • 如果应用内容超过了为本地缓存指定的本地磁盘配额,本地缓存初始化可能会失败。 有关详细信息,请参阅本地缓存概述

  • 自定义预热期间,会在内部发出 HTTP 请求(而不通过外部 URL)。 Web.config 中的某些 URL 重写规则可能会导致这些请求失败。例如,有关重定向域名或强制实施 HTTPS 的规则可能会阻止预热请求访问应用代码。 若要解决此问题,请修改重写规则,在其中添加以下两个条件:

    <conditions>
      <add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
      <add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
      ...
    </conditions>
    
  • 即使不执行自定义预热,URL 重写规则也可能仍会阻止 HTTP 请求。 若要解决此问题,请修改重写规则,在其中添加以下条件:

    <conditions>
      <add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
      ...
    </conditions>
    
  • 槽交换之后,应用可能会遇到意外的重启。 这是因为,在交换之后,主机名绑定配置会失去同步,这种情况本身不会导致重启。 但是,某些基础存储事件(例如存储卷故障转移)可能会检测到这些差异,因而强制所有工作进程重启。 为了尽量减少这种重启,请在所有槽中设置 WEBSITE_ADD_SITENAME_BINDINGS_IN_APPHOST_CONFIG=1 应用设置。 但是,此应用设置不适用于 Windows Communication Foundation (WCF) 应用。

后续步骤

阻止对非生产槽的访问