Amazon CloudFrontがCDN-オリジン間のパフォーマンスを計測するServer Timingに対応しました

2022.04.01

Webサーバーのパフォーマンスを計測する Server Timing という規格が W3Cによって策定されており、サーバーが決められたフォーマットでメトリクスをレスポンスに含めると、Server Timing に対応したブラウザからメトリクスを簡単に確認できます。

W3C : Server Timing

この仕様のエディターは、Akamai と Google のエンジニアであり、Akamai の CDN では何年も前から Server Timing を有効にでき、Chrome ブラウザからメトリクスを確認できました。

Using CDN Server Timing to Monitor CDN and Origin Performance | Akamai Developer

今回のアップデートにより、Amazon CloudFront もCDN-オリジン間の通信に対してこの Server Timing を返せるようになりました。

やってみた

Server Timing を返すには、Server Timing を有効にしたカスタム・レスポンス・ヘッダー・ポリシーを作成し、Behaviorに適用します。

レスポンス・ヘッダー・ポリシーの作成

レスポンス・ヘッダー・ポリシー の設定画面に Server-Timing header の項目が追加されています。

これを有効化(Enable)し、サンプリングレートを0−100の範囲で指定します。

レートはレスポンスに Server Timing ヘッダーを含める割合です。

特殊なリクエストを送信すると、レートによらずに、強制的に Server Timing ヘッダーを含めることもできます。

Behaviorにポリシーの適用

Behavior の Response headers policy で作成したポリシーを適用します。

レスポンスを確認

CloudFrontにアクセスして Server Timingレスポンスを確認します。

レスポンスヘッダーに Server Timing 用の

server-timing: key1;value1,key2;value2,...

というヘッダーが追加されています。

キャッシュミス時

accept-ranges: bytes
content-length: 14
content-type: text/html
date: Thu, 31 Mar 2022 19:57:48 GMT
etag: "910c8bc73110b0cd1bc5d2bcae782511"
last-modified: Wed, 20 Jan 2021 14:43:24 GMT
server: AmazonS3
server-timing: cdn-upstream-layer;desc="EDGE",cdn-upstream-dns;dur=0,cdn-upstream-connect;dur=41,cdn-upstream-fbl;dur=74,cdn-cache-miss,cdn-pop;desc="TXL52-C1",cdn-rid;desc="O7AyjtKd7IwOozuiFo0cvztVcPE3nUuQTSyl3_QBOoTAQvm1HvQmdQ=="
via: 1.1 81db6db0bc548ca5046f3395364a3666.cloudfront.net (CloudFront)
x-amz-cf-id: O7AyjtKd7IwOozuiFo0cvztVcPE3nUuQTSyl3_QBOoTAQvm1HvQmdQ==
x-amz-cf-pop: TXL52-C1
x-cache: Miss from cloudfront

このレスポンスの server-timing からは、

  • リクエストがキャッシュミスしたこと (cdn-cache-miss)
  • POP がオリジンにリクエストしたこと (cdn-upstream-layer;desc="EDGE"
  • コネクションの確立に41ミリ秒、TTFB(first byte latency)に74ミリ秒要したこと (cdn-upstream-connect;dur=41,cdn-upstream-fbl;dur=74)

などがわかります。

キャッシュヒット時

HTTP/2 200
content-type: text/html
content-length: 14
date: Thu, 31 Mar 2022 20:06:02 GMT
last-modified: Wed, 20 Jan 2021 14:43:24 GMT
etag: "910c8bc73110b0cd1bc5d2bcae782511"
accept-ranges: bytes
server: AmazonS3
x-cache: Hit from cloudfront
via: 1.1 89507e1fe7f6498a3cc1e132cbae3e50.cloudfront.net (CloudFront)
x-amz-cf-pop: TXL50-P2
x-amz-cf-id: WRaaEVfOxkZ_Y1nuQLkMQa4xyMGtjnaHpq3DBPk_l5ST7OTZbcEXLg==
age: 18
server-timing: cdn-cache-hit,cdn-pop;desc="TXL50-P2",cdn-rid;desc="WRaaEVfOxkZ_Y1nuQLkMQa4xyMGtjnaHpq3DBPk_l5ST7OTZbcEXLg==",cdn-hit-layer;desc="EDGE"

このレスポンスの server-timing からは、

  • リクエストがキャッシュヒットしたこと (cdn-cache-hit)
  • POP がキャッシュヒットしたこと (cdn-hit-layer;desc="EDGE")

などがわかります。

キャッシュヒット時はオリジンへのリクエストが発生しないので、cdn-upstream-xxx 系の値は存在しません。

フィールドの詳細はドキュメントをご確認ください。

Understanding response headers policies - Amazon CloudFront

cdn-upstream-xxx の読み取り方

CloudFront の server timing 用のメトリックとして

  • cdn-upstream-dns : Contains a value with the number of milliseconds that were spent retrieving the DNS record for the origin. A value of zero (0) indicates that CloudFront used a cached DNS result or reused an existing connection.
  • cdn-upstream-connect : Contains a value with the number of milliseconds between when the origin DNS request completed and a TCP (and TLS, if applicable) connection to the origin completed. A value of zero (0) indicates that CloudFront reused an existing connection.
  • cdn-upstream-fbl : Contains a value with the number of milliseconds between when the origin HTTP request is completed and when the first byte is received in the response from the origin (first byte latency).

が存在します。

cdn-upstream-fbl の解釈には注意が必要です。

メトリック名から類推すると、sever timing の cdn-upstream-fbl は Chrome Timing の Waiting(TTFB) と同等の意味と解釈したくなります。

具体的には、キャッシュミス時には、オリジンへのリクエストが発生するため、ビューアーがエッジにリクエストを投げてからレスポンスが戻ってくるまで(=Waiting(TTFB))の時間内にCloudFrontからオリジンへのリクエストが行われるはずで、下図のようになることを期待したくなります。

改めて Chrome の Dev Tools からメトリクスを確認すると

Waiting(TTFB)[85.52 ms] < cdn-upstream-dns[0 ms] + cdn-upstream-connect[41.00 ms] + cdn-upstream-fbl[74.00 ms]

となっています。

CloudFrontからオリジンへのリクエスト処理時間(cdn-upstream-xxx の合計)がTTFBを超えるのはおかしいですね。

cdn-upstream-fbl は DNS 名前解決や TCP スリーウェイハンドシェイクや TLS ハンドシェイクの時間 (つまり cdn-upstream-dnscdn-upstream-connect) も含んでいるためです。

TTFB のように、リクエスト完了後にレスポンスが戻ってくるまでの時間ではないことに注意しましょう。

※ AWS サポートで定義を確認済み

強制的に server timing を返す

レスポンスに server timing を含める割合は、ポリシーのサンプリングレートで指定します。

サンプリングレートに100以外の値を設定すると、レスポンスによっては server timing が含まれないことがあります。 極端な例では、サンプリングレートを0にすると、通常は server timing が一切含まれません。

リクエストヘッダーに Pragma: server-timing を渡すと、強制的に server timing をかえすことができます。

$ curl \
  -H "Pragma: server-timing" \
  -I https://example.com/index.html

まとめ

Amazon CloudFront がServer Timingに対応し、オリジンとの通信の様々なインサイトをレスポンスヘッダーから得られるようになりました。

アクセスログに依存することが多かったパフォーマンスのモニタリングも、今後は Server Timing と補完し合うことになるでしょう。

クライアントが得られる情報が大幅に増えるため、トラブルシュートが捗るのではないかと思います。

それでは。

参考