Amazon CloudFrontとEC2(Nginx)で作る国・地域対応Webサイト構築
ども、大瀧です。
CloudFrontによるグローバル対応サイトの構築は、横田の以前のエントリーでRoute 53と組み合わせを紹介済みですが、Route 53のレイテンシーレコードはAWSのリージョンごとの区分けなので、「日本」向けや「台湾」向けなど特定の国や地域別にコンテンツを区別する用途には向いていません。
そこで今回は、7月にリリースされたCloudFrontのジオターゲティング機能を利用して、国・地域に対応するWebサイトを構築してみます。まずは構成図をどーんと。
CloudFrontのジオターゲティングは国・地域の地理データベースとクライアントの接続元IP照合するのですが、その結果をオリジンに転送するHTTPリクエストのヘッダに付与します。国・地域によってオリジンを振り分ける機能ではありませんので、CloudFrontのジオターゲティングによって付与されたHTTPヘッダを解釈するためのオリジンを置くところがポイントです。静的コンテンツであれば、オリジンをS3で済ませたいところですが、S3には現状ヘッダによってコンテンツを変える機能が無いため、CloudFront+S3では対応できません。今回はオリジンとして、EC2インスタンスでNginxを構成してみます。
1. CloudFrontの構成
まずは、CloudFrontのDestribution設定で地理データをヘッダに付与するように構成します。Distribution作成時の[Default Cache Behavior Settings]画面のForward HeadersをWhitelistに変更します。
付与するヘッダ一覧からCloudFront-Viewer-Countryを選択し、[Add]をクリックして追加します。
これでOKです。実際のヘッダの動きについては、佐々木のブログ記事を参照ください。
2. Nginxの構成
続いて、オリジンとなるEC2インスタンスのNginxの構成です。今回は日本(JP)、台湾(TW)、中国(CN)向けのコンテンツを/jp、/tw、/cn以下で提供するようドキュメントルートにコンテンツを配置しました。
$ tree /usr/share/nginx/html/ /usr/share/nginx/html/ ├── 404.html ├── 50x.html ├── cn │ └── index.html ├── index.html ├── jp │ └── index.html └── tw └── index.html
そして、ドメイン宛(http://example.com/)にリクエストが来ると、HTTPヘッダを見て各国別コンテンツにリダイレクトさせる構成にしてみます。Nginxの構成ファイルnginx.conf内では、リクエストのHTTPヘッダを変数$http_<ヘッダ名のハイフンを_に置換したもの>で参照できます。今回CloudFrontが付与するヘッダはCloudFront-Viewer-Countryなので、$http_cloudfront_viewer_countryをifディレクティブの条件にし、HTTP301でリダイレクトさせるrewriteディレクティブを定義しました。
: server { listen 80; server_name example.com; root /usr/share/nginx/html; : location = / { if ( $http_cloudfront_viewer_country = JP ) { rewrite ^ http://example.com/jp/ permanent; } if ( $http_cloudfront_viewer_country = TW ) { rewrite ^ http://example.com/tw/ permanent; } if ( $http_cloudfront_viewer_country = CN ) { rewrite ^ http://example.com/cn/ permanent; } } } :
では、Nginxを起動し、動作を確認してみます。
$ sudo service nginx start Starting nginx: [ OK ] $ curl -I http://localhost/ HTTP/1.1 200 OK Server: nginx/1.0.15 Date: Sun, 02 Nov 2014 15:19:31 GMT Content-Type: text/html Content-Length: 3698 Last-Modified: Fri, 26 Apr 2013 20:36:51 GMT Connection: keep-alive Accept-Ranges: bytes $ curl -I --header "CloudFront-Viewer-Country:JP" http://localhost/ HTTP/1.1 301 Moved Permanently Server: nginx/1.0.15 Date: Sun, 02 Nov 2014 15:19:00 GMT Content-Type: text/html Content-Length: 185 Connection: keep-alive Location: http://example.com/jp/ $
いい感じですね!EC2インスタンスをオリジンに設定したCloudFront経由のリクエストも、以下のように確認できます。
$ curl -I http://XXXXXXXXXXXXXX.cloudfront.net/ HTTP/1.1 301 Moved Permanently Content-Type: text/html Content-Length: 185 Connection: keep-alive Server: nginx/1.0.15 Date: Sun, 02 Nov 2014 15:26:03 GMT Location: http://example.com/jp/ X-Cache: Miss from cloudfront Via: 1.1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.cloudfront.net (CloudFront) X-Amz-Cf-Id: abTQJX3FDe5EVQmseuN4rNuzKzQCMdn0O96oedCeKcbnLtO6gV4iEQ== $
応用編 S3 Static Website Hostingとの組み合わせ
静的Webサイトであれば、EC2インスタンスの負荷軽減と可用性を考慮してリダイレクト先をS3 Static Website Hostingでホストしても良いでしょう。CloudFrontのデフォルトオリジンをS3 Static Website Hostingのエンドポイントにし、ドメイン宛のアクセス(/)をEC2オリジンに指定することで実現できます。
運用編 キャッシュ期限の調整
運用にあたっては、CloudFrontでのコンテンツのキャッシュ期限の調整が必要です(CloudFrontでは、HTTP301リダイレクトも例外なくキャッシュ対象になります)。CloudFrontのキャッシュ期限は、基本的にはオリジンからのレスポンスに含まれるHTTPヘッダをCloudFrontが読み取って決定します(詳細は都元のエントリーを参照ください)。Nginxでは、expiresディレクティブでExpiresヘッダとCache-Controlヘッダをよしなに調整できます。
: server { listen 80; server_name example.com; root /usr/share/nginx/html; expires 10m; } :
最適なキャッシュ期限は、オリジンへの負荷耐性とコンテンツの更新頻度でバランスさせることになります。また、キャッシュ率などの分析はCloudFrontのアクセス分析機能を利用すると良いでしょう。こちらのエントリーを参考にしてください。
まとめ
CloudFrontが付与するHTTPヘッダCloudFront-Viewer-CountryをNginxで条件分岐する、国・地域別Webサイト構築の構成を紹介しました。
コンテンツの配置や振り分け方で様々な組み合わせがあると思いますが、比較的シンプルに実現できる一例として参考になれば幸いです。