LambdaオリジンのCloudFrontにおけるLambda@EdgeとOriginShieldの効果を試してみた

LambdaオリジンのCloudFrontにおけるLambda@EdgeとOriginShieldの効果を試してみた

ambda関数URLをオリジンとするCloudFront配信において、Lambda@EdgeとOrigin Shieldの有効性を検証。Origin Shieldによるリージョン間通信のレイテンシ改善効果を確認できました。
Clock Icon2025.02.20

WebAPI として公開されているデータ (JSON) を、Lambda で参照・加工し、CloudFront で公開する仕組みを実現するにあたり、CloudFront の Lambda@Edge、Origin Shield による最適化を検討しました。その効果を確認するため、性能測定を試みた結果について紹介します。

CloudFront2Lambda

計測方法

Route53ヘルスチェク計測

Route53

CloudFrontを対象としたRoute53のヘルスチェックを、3リージョン(バージニア、東京、シンガポール)から実行しました。

    Type: AWS::Route53::HealthCheck
    Properties:
      HealthCheckConfig:
        FullyQualifiedDomainName: !Sub ${CloudFrontDistribution.DomainName}
        Port: 443
        Type: HTTPS
        ResourcePath: /url/
        RequestInterval: 30
        FailureThreshold: 3
        EnableSNI: true
        Regions:
          - us-east-1 
          - ap-northeast-1 
          - ap-southeast-1

Lambda

性能測定のターゲットとなるダミーのLambda関数を、バージニアリージョンに設置しました。

exports.handler = async (event) => {
  await new Promise(resolve => setTimeout(resolve, 100));
  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'no-store'
    },
    body: JSON.stringify(event, null, 2)
  };
};
  • 200ms待機後、入力内容をJSONで出力
  • Cache-Controlはキャッシュ禁止 (no-store)

CloudFront

Origins

  • オリジンとしてLambda関数URLを指定
  • オリジンシールドを有効にする場合、バージニアを利用
        Origins:
          - Id: LambdaUrl
            DomainName: !Select [2, !Split ['/', !GetAtt UrlFunctionUrl.FunctionUrl]]
            CustomOriginConfig:
              HTTPSPort: 443
              OriginProtocolPolicy: https-only
            OriginShield:
                Enabled: true
                OriginShieldRegion: us-east-1             

Behaviors

  • 関数URL用(/url/)と、Lambda@Edge用(/edge/)の設定を用意。
  • TTLは全て0、キャッシュ利用しない設定としました。
        CacheBehaviors:
          - PathPattern: /url/*
            TargetOriginId: LambdaUrl
            ViewerProtocolPolicy: https-only
            ForwardedValues:
              QueryString: true
              Cookies:
                Forward: none
              Headers: []
            MinTTL: 0
            DefaultTTL: 0
            MaxTTL: 0
            AllowedMethods:
              - GET
              - HEAD
          - PathPattern: /edge/*
            TargetOriginId: S3website
            ViewerProtocolPolicy: allow-all
            LambdaFunctionAssociations:
              - EventType: origin-request
                LambdaFunctionARN: !Ref EdgeFunctionVersion
            AllowedMethods:
              - GET
              - HEAD
            ForwardedValues:
              QueryString: true
              Cookies:
                Forward: none
              Headers: []
            MinTTL: 0
            DefaultTTL: 0
            MaxTTL: 0

CloudWatchLogs Insights

CloudWatchLogsに保存した CloudFront の 標準アクセスログ(v2)、12時間分を対象にCloudWatchLogs Insightsを利用して集計を試みました。

fields @timestamp, @message
| parse @message /\"cs-uri-stem\":\"(?<uri>[^\"]+)\"/ 
| parse @message /\"c-country\":\"(?<country>[^\"]+)\"/ 
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"x-edge-location\":\"(?<location>[^\"]+)\"/ 
| parse @message /\"x-edge-result-type\":\"(?<result_type>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| parse @message /\"sc-status\":\"(?<status>[^\"]+)\"/ 
| filter useragent like 'Amazon-Route53-Health-Check-Service%'
| filter country in ["US", "JP", "SG"] 
| stats count() as request_count, 
        sum(timetaken) as total_time, 
        avg(timetaken) as avg_time ,
        percentile(timetaken, 10) as p10_time ,
        percentile(timetaken, 50) as p50_time ,
        percentile(timetaken, 95) as p95_time 
  by country,location,result_type, uri, status
| sort p50_time

結果

Lambda関数URL

  • オリジンシールドなし
country location avg_time p10_time p50_time p95_time
US IAD12-P2 0.2222 0.217 0.22 0.235
JP NRT12-P1 0.6642 0.6442 0.6585 0.7387
SG SIN52-P1 0.8609 0.8437 0.8556 0.9022
  • オリジンシールド有効
country location avg_time p10_time p50_time p95_time
US IAD61-P8 0.2247 0.22 0.223 0.231
JP NRT57-P4 0.3769 0.3673 0.3721 0.3881
SG SIN2-P1 0.4455 0.431 0.4362 0.4513

Lambda@Edge

  • オリジンシールドなし
country location avg_time p10_time p50_time p95_time
US IAD12-P2 0.2239 0.219 0.222 0.232
JP NRT12-P1 0.2259 0.219 0.224 0.236
SG SIN52-P1 0.2217 0.217 0.22 0.23
  • オリジンシールド有効
country location avg_time p10_time p50_time p95_time
US IAD61-P8 0.2307 0.223 0.227 0.251
JP NRT57-P4 0.3823 0.3651 0.371 0.4433
SG SIN2-P1 0.4454 0.4323 0.4384 0.4802

考察

オリジンシールドを有効にすることで、東京(NRT)とシンガポール(SIN)において、Lambda関数URLの場合、レイテンシが大幅に改善されることが確認できました。

  • 東京:0.6642秒 -> 0.3769秒 (約43%削減)
  • シンガポール:0.8609秒 -> 0.4455秒 (約48%削減)

今回の検証、キャッシュは効かせない指定をしていましたが、エッジからオリジンまでの通信経路の最適化にオリジンシールドが効果を発揮したものと予想されます。

Lambda@Edge、オリジンシールドのない状態では、3リージョンとも、バージニアリージョンに設置したLambda関数URLと同等のレイテンシで利用する事ができました。

オリジンシールドを有効化した場合、Lambda@Edgeの実行環境がオリジンシールドを設置したバージニアリージョンとなるため、Lambda@Edgeの最寄りのエッジで実行される特性が失われた模様です。

まとめ

Lambda@Edge 、高速な実行環境として利用できる可能性が確認できました。

しかしながら以下の点を考慮し、今回は Lambda@Edge の採用は見送り、Lambda 関数 URL と、必要に応じてオリジンシールドによる最適化を試みる方針です。

  • エッジとオリジンが同じリージョンの場合、Lambda@Edge 性能面での優位性は少ない。
  • エッジのキャッシュ利用率が高い場合や、オリジンシールドの利用により優位性は低くなる。
  • 通常のLambdaであれば、環境変数の利用や30秒以上の実行時間に設定可能。
  • デプロイ、ログなどの管理性も、Lambda@Edgeより通常のLambdaが優れる
  • Lambdaの関数URL直接実行されるリスクについては、OACサポートにより回避可能

構成図

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.