こんにちは、クレスコの北垣です。
以前、「生成AI時代のサーバレスAPI構成」 というタイトルで、ストリーミングレスポンスを実現するAWSサーバレスAPI構成について整理し記事にしました。今回はその中で紹介した CloudFront + Lambda Function URLs (Lambda Web Adapter利用) の構成でストリーミングレスポンスAPIをセキュアに実装する方法やパフォーマンスチューニングの手法について解説します。
目次
- Lambda Web Adapter概要
- アーキテクチャ概要
- 実装
- パフォーマンスチューニング
- まとめ
※ 注意 - 本記事の内容は2025年1月7日時点の情報で記載しております。
1. Lambda Web Adapter概要
Lambda Function URLs を利用してストリーミングレスポンスを実現する手法は、 以下の3パターンで利用可能です。(公式ドキュメントリンク)
- Node.js マネージドランタイム
- カスタムランタイム
- Lambda Web Adapter
特に Lambda Web Adapter は、既存のWebアプリをほぼそのままLambda環境で実行可能にする 便利なツールです。
Lambda Web Adapter の特徴
- 従来のウェブアプリケーションを、ほぼそのまま Lambda 上で動作させることができ、HTTPを使用するウェブサーバーアプリケーションに対応しています。対応しているフレームワークは以下の通りです。
- Python: FastAPI, Flask
- Node.js: Express.js, Next.js
- Java: SpringBoot
- Rust: Axum
- Go: Gin
- Dockerfileに1行追加するだけで導入が完了します。そのため既存のWebアプリケーションコードの変更は最小限となります。ECSへの移行も容易です。
Lambda Web Adapter の動作する仕組み
Lambda Web AdapterはHTTPリクエストを受け取り、従来のWebサーバーアプリケーションが理解できる形に変換します。この変換により、通常のウェブフレームワークをサーバレス環境に適応させることが可能です。詳細は以下リンク先を参照ください。
2. アーキテクチャ概要
Lambda Function URLs だけでAPIを公開するにはセキュリティの面で不十分な場合があります。そのため、CloudFrontを前段に置き、他のAWSサービスと組み合わせてセキュリティを強化する構成を推奨します。
以下、構成の例です。

補足説明
- CloudfrontにWAFを統合することで、エッジロケーションでWAFルールが適用できオリジンサーバ(Lambda)に到達する前に攻撃を遮断可能(DDoS対策やIP制限も可能)
- Lambda@Edge / Cognitoを利用した認証認可、またはSecrets Managerを利用したAPIキー認証によるセキュリティの強化
- Lambda Function URLsのリソースポリシーを使用してCloudFrontからのアクセスのみを許可
3. 実装
ここでは AWS Samplesで提供されているアプリをベース に、Lambda Web Adapterを利用したアプリケーションの構築を行う際に 注意すべき点にフォーカス して解説します。
▼利用するAWS Samplesのリポジトリ
https://github.com/aws-samples/bedrock-access-gateway
※Amazon Bedrock 向け OpenAI 互換 RESTful APIを提供しているアプリです
▼ AWS Lambda Web Adapterのリポジトリ
https://github.com/awslabs/aws-lambda-web-adapter
▼前提
- AWS環境構築には、ローカルの環境構築不要で利用可能な AWS Cloudshell を利用することをお勧めします。以降、Cloudshell利用前提で記載します。
- Amazon Bedrockの最新LLMを利用可能な us-east-1(バージニア北部) リージョンを利用します(利用するLLMは事前にアクセスできるようにしておきます。詳細は こちら を参照ください。)
- 以下の構成を構築します

(1) リポジトリをCloneし、Lambda Web Adapterを利用可能な定義に変更します。
bedrock-access-gateway のリポジトリをCloneします。
[cloudshell-user@ ~]$ git clone https://github.com/aws-samples/bedrock-access-gateway.git [cloudshell-user@ ~]$ cd bedrock-access-gateway/ [cloudshell-user@ bedrock-access-gateway]$ |
Cloneしたら、定義を変更してきます。
対象ソース①:src/Dockerfile
# 追加コード(2行目) [ Lambda Web Adapterを利用するための定義 ] COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.9.0 /lambda-adapter /opt/extensions/lambda-adapter # 変更コード(10-11行目) [ Lambda Web Adapterを利用時の定義変更] ENTRYPOINT ["uvicorn"] CMD [ "api.app:app", "--host", "0.0.0.0", "--port", "8080"] |
修正サンプル(画像右側が修正後):

対象ソース②:src/api/app.py
# コメントアウト(50行目) [ Mangumはストリーミングレスポンス非対応のため利用しない ] #handler = Mangum(app) |
修正サンプル(画像右側が修正後):

(2) Dockerビルド実行しAWS ECRにイメージを登録します。
シェルスクリプトが用意されていますが、Cloudshellで実行可能とするために、以下修正します。
対象ソース③:scripts/push-to-ecr.sh
# arm64の定義削除(12行目) [ Cloudshellはarm64のDockerビルドに非対応 ] ARCHS=("amd64") # コメントアウト(77行目) [ 今回はECS用イメージ不要 ] #build_and_push_images "bedrock-proxy-api-ecs" "$TAG" |
修正サンプル(画像右側が修正後):

修正後、スクリプトを実行するとECRにコンテナイメージが登録されます。
[cloudshell-user@ bedrock-access-gateway]$ cd scripts/ [cloudshell-user@ scripts]$ bash ./push-to-ecr.sh |
(3) 認証用のAPIKeyをパラメータストアに登録します。
APIKeyの値はご自身で決めたものを指定してください。
[cloudshell-user@ scripts]$ aws ssm put-parameter --name "BedrockProxyAPIKey" --type "SecureString" --value "<APIKeyの値を決めて指定する>" |
(4) Cloudformation templateコードを作成します。
以下、Cloudformationコードを、deployment/clf-bedrock-proxy-api-custom-template.yamlとして登録します。
|
重要な点、ハマりどころについて解説した図がこちらです。

(5) Cloudformationを実行します。
実行パラメータにアクセスを許可するIPアドレスを指定してください。
[cloudshell-user@ bedrock-access-gateway]$ aws cloudformation create-stack --stack-name BedrockProxyStack --template-body file://./deployment/clf-bedrock-proxy-api-custom-template.yaml --parameters ParameterKey=BastionIpAddress,ParameterValue="<許可するIPアドレスを指定してください>/32" --capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND |
※7分程度でデプロイが完了します
完了後、出力リソースを確認し、APIエンドポイントを確認します。
[cloudshell-user@ bedrock-access-gateway]$ aws cloudformation describe-stacks --stack-name BedrockProxyStack --query "Stacks[0].Outputs" [ { "OutputKey": "ApiEndpoint", "OutputValue": "https://xxxxxxxxxxxxxxxxxx.cloudfront.net/api/v1", "Description": "API Endpoint URL" } ] [cloudshell-user@ bedrock-access-gateway]$ |
これでAWSの環境構築は完了です。
(6) コード生成AIサービスから利用してみる
オープンソースのコード生成AIツール「Continue.dev」を使用し、本記事で作成したAPIに接続させてみます。(Continue.devの概要や利用方法については 公式サイト をご参照ください。)
VS CodeにContinue.dev拡張機能を導入し、設定Jsonファイルを定義します。
{ "models": [ { "model": "us.anthropic.claude-3-5-sonnet-20241022-v2:0", "contextLength": 128000, "title": "us.anthropic.claude-3-5-sonnet-20241022-v2:0", "systemMessage": "You are an expert in software development. You give kind and concise answers in Japanese.", "provider": "openai", "apiKey": "<ご自身で指定したAPIキーの値>", "apiBase": "https://<ここに発行されたCloudfrontドメインを指定する>.cloudfront.net/api/v1", "useLegacyCompletionsEndpoint": false, "completionOptions": { "temperature": 1, "maxTokens": 4096, "stream": true } } ] } |
あとは利用するだけです。

画像だと伝わりませんが、ストリーミングレスポンスで回答が画面に表示されます。
マルチモーダルの問い合わせも可能ですし、プログラムに関係ない通常のチャットツールとしても利用可能です。

4. パフォーマンスチューニング
Lambda Web Adapterを利用すると、コールドスタートの影響で性能が思ったほど出ないことがあります。Lambdaのコールドスタート対策では、Provisioned Concurrency を利用する または SnapStart を利用する の2パターンが主流かと思います。
SnapStartは特定のランタイムのみサポートされているため、コンテナイメージを利用している場合はProvisioned Concurrencyを利用して対策します。
※注意
Provisioned Concurrencyは無料枠が無く、設定内容に応じてコストが掛かる点にご注意ください。
設定方法や注意点など、Provisioned Concurrencyの詳細について以下リンク先を参照ください。
https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html
5. まとめ
Lambda Web Adapterは、従来のWebアプリケーションをAWSのサーバレス環境へ容易に移行する強力なツールです。本記事で紹介したアーキテクチャと実装方法を活用することで、以下の利点が得られます:
(1) 簡単な移行:
既存のWebアプリケーションをほぼそのままLambda上で動作させることができます。
(2) セキュリティの強化:
CloudFrontとWAFを組み合わせることで、エッジでの防御が可能になり、DDoS攻撃やIPアドレス制限などの対策が実現できます。
(3) パフォーマンスの最適化:
Provisioned Concurrencyを利用することで、コールドスタートの問題を軽減し、応答性能を向上させることができます。
(4) 柔軟性:
Amazon Bedrockなどの最新のAWSサービスとの統合が容易になり、AIを活用したアプリケーションの開発が可能です。
(5) コスト効率:
サーバーレスアーキテクチャにより、使用した分だけ課金されるため、リソースの無駄を削減できます。
この構成は、特にAI機能を備えたWebアプリケーションや、高いセキュリティが要求されるAPIの構築に適しています。ただし、Provisioned Concurrencyのコストには注意が必要です。
今後のクラウド開発において、このようなサーバーレスアーキテクチャの活用はますます重要になると考えられます。本記事の内容が参考になれば幸いです。