LambdaオリジンのCloudFrontにおけるLambda@EdgeとOriginShieldの効果を試してみた
WebAPI として公開されているデータ (JSON) を、Lambda で参照・加工し、CloudFront で公開する仕組みを実現するにあたり、CloudFront の Lambda@Edge、Origin Shield による最適化を検討しました。その効果を確認するため、性能測定を試みた結果について紹介します。
計測方法
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サポートにより回避可能