Azure App Service のスロットスワップ時の挙動について

Web Apps や Functions の本番運用では、リリース作業時に本番環境のダウンタイム、レスポンス遅延などを最小限に抑えるため、スロットのスワップ機能が利用できる。

スワップ機能を一言で説明すると、「prd スロットをあらかじめ最新化しておいた stg スロットと交換することで、ダウンタイムなしで最新環境にする」となるが、裏ではその実現のために結構色々行われており、その内容を多少は理解してないと、スワップ時に問題が発生する可能性がある。

スワップ時の流れとしては以下となる。

  1. Azure ポータルでスワップ開始
  2. ソーススロット (stg) のアプリ設定を、ターゲットスロット (prd) のアプリ設定に変更する。またこの際、「デプロイスロット設定」も考慮される
  3. stg スロットのアプリ設定変更により、stg のワーカープロセス再起動が発生する。新しいアプリ設定で stg スロットが使用可能になるまで、数十秒かかる
  4. stg スロットが prd アプリ設定として完全に使用可能になったら、prd と stgFQDNスワップを行う
  5. この時点では、クライアントからのリクエストは、prd URL へのリクエスト、stg URL へのリクエスト共に、prd, stg のどちらのスロットにも転送される可能性がある (スロット上はどちらも prd アプリ設定の状態)
  6. FQDN 付け替えも数十秒ほど経つと完全に切り替え完了し、prd URL へのリクエストは旧 stg スロット、stg URL へのリクエストは旧 prd スロットにのみ転送されるようになる。この時点で、本番環境としては完全にスワップ完了し、最新バージョンのアプリで稼働している状態となる
  7. stg スロットのアプリ設定を、stg のアプリ設定に変更する
  8. stg スロットのアプリ設定変更により、stg のワーカープロセス再起動が発生する。新しいアプリ設定で stg スロットが使用可能になるまで、数十秒かかる
  9. stg スロットが、stg アプリ設定及び旧 prd 上で稼働していたアプリのバージョンが稼働している状態となる
  10. 全てのスワップ作業完了

ここでは実際に両方の環境へ HTTP リクエストし続けた状態でスワップを行い、状況を観察する。検証環境は Function App (App Service プラン) だが、Web Apps でも基本は同じかと思われる。

ただ、従量課金プランや複数インスタンス運用時は、細かいところで多少差異があるかもしれない(未確認)。

基本環境

対象 設定
プラットフォーム Function v3 (.NET Core)
OS Windows
プラン App Service プラン (S1)
インスタンス 1
常時接続 オン
アプリ設定のデプロイスロット設定 明記しない限り全てオン

スワップ前の prd 環境

アプリ設定 (Azure ポータル)
名前 デプロイ スロットの設定
FixAppSetting fixPrd オン
SwapAppSetting swap1 オフ
アプリバージョン (プログラム ハードコード)
名前
AppVer 1.0

スワップ前の stg 環境

アプリ設定 (Azure ポータル)
名前 デプロイ スロットの設定
FixAppSetting fixStg オン
SwapAppSetting swap2 オフ
アプリバージョン (プログラム ハードコード)
名前
AppVer 2.0

デプロイする Function コード

呼ばれたら 2 秒待機して、必要な情報を返すだけの HTTP トリガー

public static class Function1
{
    private static IConfigurationRoot Configuration { get; }
    const string APP_VER = "2.0";

    static Function1()
    {
        var builder = new ConfigurationBuilder()
    .AddJsonFile("local.settings.json", true)
    .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    [FunctionName("Function1")]
    public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        string fixAppSetting = Configuration["FixAppSetting"];
        string swapAppSetting = Configuration["SwapAppSetting"];
        string slotName = Configuration["WEBSITE_SLOT_NAME"];
        string instanceId = Configuration["WEBSITE_INSTANCE_ID"];
        var processId = System.Diagnostics.Process.GetCurrentProcess().Id;

        string param = req.Query["param"];

        await Task.Delay(2 * 1000);

        return (ActionResult)new OkObjectResult(string.Format("Param: {0}, AppVer: {1}, FixAppSetting: {2}, SwapAppSetting: {3}, SlotName: {4}, ShortInstanceId: {5}, ProcessId: {6}",
            param, APP_VER, fixAppSetting, swapAppSetting, slotName, instanceId.Substring(0, 6), processId));
    }
}

HTTP リクエストを行うコード (PowerShell)

PowerShell を使って、3 秒間隔で 35 回リクエストを行う。
2 window 使って prd と stg 向けに同時実行するが、実行コードの差異はリクエスト URL 情報のみ。

参考: PowerShell で連続的な HTTP リクエストを送る - poke_dev’s blog

$maxCount = 35
$waitSeconds = 3

for ($i = 1; $i -le $maxCount; $i++){
    Write-Output($i.ToString() + "/" + $maxCount.ToString())

    Start-Job -ScriptBlock{
        param(
            [string] $param
        )

        $startTime = [DateTime]::Now

        Write-Output("(" + $param + ") " + $startTime.ToString("[MM/dd HH:mm:ss]") + " requesting...")

        $url = "https://functestcore31std.azurewebsites.net/api/Function1?param=prd_" + $param

        Invoke-RestMethod -Method Get -Uri $url

        $endTime = [DateTime]::Now
        $duration = $endTime - $startTime
        Write-Output("(" + $param + ") " + $endTime.ToString("[MM/dd HH:mm:ss]") + " response time: " + $duration.TotalSeconds.ToString("N2") + " (s)")
    } -ArgumentList $i

    Start-Sleep $waitSeconds
}

While ($runningJobs = Get-Job -State "Running"){
    Write-Output("Still running... (" + $runningJobs.ChildJobs.Count + " jobs)")
    Start-Sleep 5
}

Write-Output "`r`nAll request completed.`r`n"

foreach ($job in Get-Job){
    Receive-Job -Job $job
    Remove-Job -Job $job
    Write-Output ""
}

スワップ時の呼び出し結果

作業タイムライン

時間 内容
21:25:05 ソースを stg、ターゲットを prd にしてスワップ開始
21:26:18 スワップ終了 (Azure ポータル上は)

スワップ時のアプリ設定状況

f:id:poke_dev:20200119010722p:plain

prd URL 呼び出し

(1) [01/18 21:24:54] requesting...
Param: prd_1, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(1) [01/18 21:24:57] response time: 2.31 (s)

(2) [01/18 21:24:57] requesting...
Param: prd_2, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(2) [01/18 21:25:00] response time: 2.18 (s)

(3) [01/18 21:25:01] requesting...
Param: prd_3, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(3) [01/18 21:25:03] response time: 2.22 (s)

(4) [01/18 21:25:04] requesting...
Param: prd_4, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(4) [01/18 21:25:06] response time: 2.19 (s)

(5) [01/18 21:25:07] requesting...
Param: prd_5, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(5) [01/18 21:25:09] response time: 2.23 (s)

(6) [01/18 21:25:10] requesting...
Param: prd_6, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(6) [01/18 21:25:12] response time: 2.26 (s)

(7) [01/18 21:25:13] requesting...
Param: prd_7, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(7) [01/18 21:25:16] response time: 2.61 (s)

(8) [01/18 21:25:16] requesting...
Param: prd_8, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(8) [01/18 21:25:18] response time: 2.23 (s)

(9) [01/18 21:25:19] requesting...
Param: prd_9, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(9) [01/18 21:25:21] response time: 2.25 (s)

(10) [01/18 21:25:22] requesting...
Param: prd_10, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(10) [01/18 21:25:24] response time: 2.19 (s)

(11) [01/18 21:25:25] requesting...
Param: prd_11, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(11) [01/18 21:25:28] response time: 2.25 (s)

(12) [01/18 21:25:28] requesting...
Param: prd_12, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(12) [01/18 21:25:31] response time: 2.46 (s)

(13) [01/18 21:25:32] requesting...
Param: prd_13, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(13) [01/18 21:25:34] response time: 2.90 (s)

(14) [01/18 21:25:35] requesting...
Param: prd_14, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(14) [01/18 21:25:37] response time: 2.81 (s)

(15) [01/18 21:25:38] requesting...
Param: prd_15, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(15) [01/18 21:25:40] response time: 2.70 (s)

(16) [01/18 21:25:41] requesting...
Param: prd_16, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(16) [01/18 21:25:43] response time: 2.21 (s)

(17) [01/18 21:25:44] requesting...
Param: prd_17, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(17) [01/18 21:25:46] response time: 2.19 (s)

(18) [01/18 21:25:47] requesting...
Param: prd_18, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(18) [01/18 21:25:49] response time: 2.19 (s)

(19) [01/18 21:25:50] requesting...
Param: prd_19, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(19) [01/18 21:25:52] response time: 2.18 (s)

(20) [01/18 21:25:53] requesting...
Param: prd_20, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(20) [01/18 21:25:55] response time: 2.20 (s)

(21) [01/18 21:25:56] requesting...
Param: prd_21, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(21) [01/18 21:25:59] response time: 2.21 (s)

(22) [01/18 21:25:59] requesting...
Param: prd_22, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(22) [01/18 21:26:02] response time: 2.20 (s)

(以降も 22 と同じレスポンスとなるため、割愛)
prd URL リクエスト結果からわかること
  • ダウンタイム、遅延ともになし
  • 17 回目のリクエスト時に stg スロット上のアプリへリクエストが転送され始めたことが分かるが、21 回目までは prd, stg スロット共に prd URL へのリクエストが転送されていることが分かる

stg URL 呼び出し

(1) [01/18 21:24:54] requesting...
Param: stg_1, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(1) [01/18 21:24:56] response time: 2.31 (s)

(2) [01/18 21:24:57] requesting...
Param: stg_2, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(2) [01/18 21:24:59] response time: 2.18 (s)

(3) [01/18 21:25:00] requesting...
Param: stg_3, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(3) [01/18 21:25:02] response time: 2.28 (s)

(4) [01/18 21:25:03] requesting...
Param: stg_4, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(4) [01/18 21:25:05] response time: 2.19 (s)

(5) [01/18 21:25:06] requesting...
Param: stg_5, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(5) [01/18 21:25:08] response time: 2.29 (s)

(6) [01/18 21:25:09] requesting...
Param: stg_6, AppVer: 2.0, FixAppSetting: fixStg, SwapAppSetting: swap2, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4204
(6) [01/18 21:25:12] response time: 2.66 (s)

(7) [01/18 21:25:12] requesting...
The service is unavailable.
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod]、WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
    + PSComputerName        : localhost
(7) [01/18 21:25:13] response time: 0.27 (s)

(8) [01/18 21:25:15] requesting...
Param: stg_8, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(8) [01/18 21:25:42] response time: 26.68 (s)

(9) [01/18 21:25:19] requesting...
Param: stg_9, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(9) [01/18 21:25:42] response time: 23.58 (s)

(10) [01/18 21:25:22] requesting...
Param: stg_10, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(10) [01/18 21:25:42] response time: 20.48 (s)

(11) [01/18 21:25:25] requesting...
Param: stg_11, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(11) [01/18 21:25:42] response time: 17.39 (s)

(12) [01/18 21:25:28] requesting...
Param: stg_12, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(12) [01/18 21:25:42] response time: 14.30 (s)

(13) [01/18 21:25:33] requesting...
Param: stg_13, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(13) [01/18 21:25:42] response time: 9.35 (s)

(14) [01/18 21:25:36] requesting...
Param: stg_14, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(14) [01/18 21:25:42] response time: 6.36 (s)

(15) [01/18 21:25:37] requesting...
Param: stg_15, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(15) [01/18 21:25:42] response time: 5.12 (s)

(16) [01/18 21:25:40] requesting...
Param: stg_16, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(16) [01/18 21:25:42] response time: 2.26 (s)

(17) [01/18 21:25:43] requesting...
Param: stg_17, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(17) [01/18 21:25:45] response time: 2.18 (s)

(18) [01/18 21:25:46] requesting...
Param: stg_18, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(18) [01/18 21:25:49] response time: 2.21 (s)

(19) [01/18 21:25:50] requesting...
Param: stg_19, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(19) [01/18 21:25:52] response time: 2.18 (s)

(20) [01/18 21:25:53] requesting...
Param: stg_20, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(20) [01/18 21:25:55] response time: 2.20 (s)

(21) [01/18 21:25:56] requesting...
Param: stg_21, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(21) [01/18 21:25:58] response time: 2.27 (s)

(22) [01/18 21:25:59] requesting...
Param: stg_22, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(22) [01/18 21:26:01] response time: 2.20 (s)

(23) [01/18 21:26:02] requesting...
Param: stg_23, AppVer: 2.0, FixAppSetting: fixPrd, SwapAppSetting: swap2, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 668
(23) [01/18 21:26:04] response time: 2.30 (s)

(24) [01/18 21:26:05] requesting...
Param: stg_24, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(24) [01/18 21:26:07] response time: 2.18 (s)

(25) [01/18 21:26:08] requesting...
Param: stg_25, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(25) [01/18 21:26:10] response time: 2.19 (s)

(26) [01/18 21:26:11] requesting...
Param: stg_26, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(26) [01/18 21:26:13] response time: 2.20 (s)

(27) [01/18 21:26:14] requesting...
Param: stg_27, AppVer: 1.0, FixAppSetting: fixPrd, SwapAppSetting: swap1, 
SlotName: Production, ShortInstanceId: 388ca9, ProcessId: 1896
(27) [01/18 21:26:17] response time: 2.24 (s)

(28) [01/18 21:26:17] requesting...
The service is unavailable.
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod]、WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
    + PSComputerName        : localhost
(28) [01/18 21:26:18] response time: 0.42 (s)

(29) [01/18 21:26:20] requesting...
Param: stg_29, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(29) [01/18 21:26:48] response time: 27.79 (s)

(30) [01/18 21:26:24] requesting...
Param: stg_30, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(30) [01/18 21:26:48] response time: 24.69 (s)

(31) [01/18 21:26:27] requesting...
Param: stg_31, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(31) [01/18 21:26:48] response time: 21.60 (s)

(32) [01/18 21:26:30] requesting...
Param: stg_32, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(32) [01/18 21:26:48] response time: 18.50 (s)

(33) [01/18 21:26:33] requesting...
Param: stg_33, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(33) [01/18 21:26:48] response time: 15.42 (s)

(34) [01/18 21:26:36] requesting...
Param: stg_34, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(34) [01/18 21:26:48] response time: 12.32 (s)

(35) [01/18 21:26:39] requesting...
Param: stg_35, AppVer: 1.0, FixAppSetting: fixStg, SwapAppSetting: swap1, 
SlotName: stg, ShortInstanceId: 388ca9, ProcessId: 4912
(35) [01/18 21:26:48] response time: 9.20 (s)
stg URL リクエスト結果からわかること
  • アプリ設定が変更された、7 回目、及び 28 回目のリクエスト近辺で、ダウンタイムと遅延が発生している
  • prd アプリ設定適用後の 8 回目リクエストからは、stg URL へのリクエストにも関わらず、prd アプリ設定でプログラムが実行されている(=危険)
  • 17 回目のリクエスト時に prd スロット上のアプリへリクエストが転送され始めたことが分かるが、23 回目までは prd, stg スロット共に stg URL へのリクエストが転送されていることが分かる (=危険)
  • stg スロット側では 2 度、アプリ設定の変更が発生する関係で、stg としての完全に稼働状態となるまで、時間がかかる

上記結果のまとめ

時間 内容 stg AppSetting stg AppVer stg ProcID prd AppSetting prd AppVer prd ProcID
21:25:05 ソース (stg)、ターゲット (prd) のスワップ開始 stg 2.0 4204 prd 1.0 1896
21:25:12 stg へ prd アプリ設定適用。プロセス再起動 - 2.0 - prd 1.0 1896
21:25:42 stg プロセス再起動完了 prd 2.0 668 prd 1.0 1896
21:25:43 stg, prd の FQDN スワップ開始 prd 1.0 1896 prd 2.0 668
21:26:05 FQDN スワップ完了 prd 1.0 1896 prd 2.0 668
21:26:17 stgstg アプリ設定適用。プロセス再起動 - 1.0 - prd 2.0 668
21:26:18 (Azure ポータル上はスワップ完了) - 1.0 - prd 2.0 668
21:26:48 stg プロセス再起動完了 stg 1.0 4912 prd 2.0 668

上記結果のまとめからわかること

  • プロセス再起動は stg スロット上でのみ発生する(=ダウンタイム、遅延も stg スロット上でのみ発生する)
  • スワップ中、stg URL へのリクエストが、prd アプリ(=prd アプリ設定)として処理されるタイミングがある。そのため、スワップ中は stg へのリクエストは遮断する必要がある(別途まとめる予定)
  • アプリ設定変更時に、ダウンタイムと遅延が発生する可能性がある。そのため、新しいアプリ設定が追加された場合は本番へのリリース方法を考慮する必要がある(別途まとめる予定)
  • 最終的な結果だけ見ると「入れ替わる」けど、その過程はソースとターゲットで全く異なる。ターゲットがダウンタイムなしで最新に切り替われるのはソースの犠牲の上に成り立ってるので、結局入れ替わるから同じじゃん的な気持ちで、ソースに prd を指定してスワップとかは間違えてもしないこと(明示的にそうスワップ設定しない限り、基本的にはないと思うが)