AWS S3のデータをリージョン間転送する方法
世界中で利用される画像/動画アプリにて、日本リージョンのS3から画像/動画を参照しているが、アメリカからのアクセスが異様に遅いという話があり。いろいろ調べてCDNを高速化した内容をここに書いていきたいと思います
Nikon デジタルカメラ COOLPIX A300 光学8倍ズーム 2005万画素 シルバー A300SL
- 出版社/メーカー: ニコン
- 発売日: 2016/05/27
- メディア: Camera
- この商品を含むブログを見る
Nikon デジタルカメラ COOLPIX A100 光学5倍 2005万画素 レッド A100RD
- 出版社/メーカー: ニコン
- 発売日: 2016/01/28
- メディア: Camera
- この商品を含むブログを見る
なんで遅いの?
ふつうに考えれば、アメリカから、日本にアクセスしてデータを取得するんだから、そりゃ遅いです汗 ちなみに、日本リージョンにあるS3ファイルを日本とアメリカから取得した場合、これくらい差があります。 公平性を出すため、AWSのEC2からアクセスしているわけではなく、conohaのVPSから計測しております。 計測は簡易的ではありますが、wgetを利用して78MBくらいのファイルを取得して時間を計測しております
結果はどうだったでしょうか?
日本からのアクセス
# wget -O /dev/null --no-proxy https://s3-ap-northeast-1.amazonaws.com/xxxxxx/yyyyyyy/test_video.mp4.mp4 > /dev/null 100%[=================================>] 81,999,254 21.6M/s in 3.6s 2017-01-11 08:42:15 (21.6 MB/s) - "/dev/null" saved [81999254/81999254]
アメリカからアクセス
# wget -O /dev/null --no-proxy https://s3-ap-northeast-1.amazonaws.com/xxxxxx/yyyyyyy/test_video.mp4.mp4 > /dev/null 100%[=================================>] 81,999,254 13.2M/s in 10s 2017-01-11 00:42:04 (7.76 MB/s) - "/dev/null" saved [81999254/81999254]
驚きなのかな?普通なのかもしれませんが、おおよそアメリカから日本のS3にアクセスする転送量は、日本から日本のS3にアクセスする転送量の3分の1になります。時間的にも、日本からのアクセスより3倍時間かかっていますよね、そりゃ遅いわ。。
ここから考えられるものは一つで、じゃあ、海外にもバケットを作ろうって話になりますよね
が、しかし。日本のs3バケットと、アメリカのs3バケットは同期してくれるのってあたりが課題になってきます
いまさらだけど、S3はレプリケーションができる!?
クロスリージョンレプリケーションという機能があり、MySQLのレプリケーションを想像してもらえばわかるかと思うのですが、リージョン間のバケットを非同期でレプリケーションしてくれる機能です。これはすごい
詳細は、こちらを確認してください
設定手順
jpバケットのプロパティから、クロスリージョンレプリケーションを選択します
- バージョニングの有効化をクリックします
- 結果、以下のような状態になりました
- これでリージョンの異なるバケットが作成できたのが確認できたかと思います
以上でレプリケーションの設定は完了ですが、一転注意があります。
レプリケーションソース内にある既存のオブジェクトに関しては、レプリケーションはされません。レプリケーション設定後のオブジェクトのみが同期されます!
なので、既存のオブジェクトに関してはあらかじめ、コピーしておきましょう。コピーペーストに関しては、s3の管理コンソールから行うことができます。
オブジェクトがものすごい数でものすごいでかい場合は、ブラウザのセッションが切れて失敗する可能性が高いので
コンソールでやるのが無難だと思います、以下ディレクトリコピーの一例ですが、再帰的な取り込みをする--recursiveオプションを入れております
- リージョン間コピーをコマンドで実施
aws s3 cp s3://backet-jp-qazwsx s3://backet-us-qazwsx --recursive
- こんな方法もあります(同期)
aws s3 sync s3://backet-jp-qazwsx s3://backet-us-qazwsx
設定後、パフォーマンス測定
では設定後、どのようにパフォーマンスが変わったでしょうか?
アメリカからアメリカのS3にアクセス
wget -O /dev/null --no-proxy https://s3.amazonaws.com/xxxxxx/yyyyy/test_video.mp4.mp4 > /dev/null 100%[========================================================================>] 81,999,254 21.8M/s in 4.4s
それと比較して
アメリカから日本のS3にアクセス
wget -O /dev/null --no-proxy https://s3-ap-northeast-1.amazonaws.com/xxxxxx/yyyyy/test_video.mp4.mp4 > /dev/null 100%[========================================================================>] 81,999,254 10.1M/s in 15s
どうでしょうか?一目瞭然ですよね?
つまり、リクエスト元の国と同じリージョンにs3バケットがあるとこんなに速度の差が出るのです!!
余談ですがnginx の設定例
たとえばですが、上記をnginxでリバースプロキシしちゃおうと考えた場合、以下のような設定になるかな?と思います
location / { root /xxxx/yyyyyy; rewrite ^/yyyyyyy/(.*)$ /yyyyyyy-us/$1 break; if ($request_uri ~* "server-status") { access_log off; } index index.html index.htm; limit_rate_after 3m; limit_rate 2m; try_files $uri $uri/ @s3 @s3jp; } location @s3 { resolver 8.8.8.8; # OpenDNS resolver_timeout 5s; proxy_pass https://s3.amazonaws.com:443; } location @s3jp { resolver 8.8.8.8; # OpenDNS resolver_timeout 5s; rewrite ^/yyyyyyy-us/(.*)$ /yyyyyyy/$1 break; proxy_pass https://s3-ap-northeast-1.amazonaws.com:443; }
try_files
上記で、nginxで設定できるtry_filesを利用しております。何をしているかというと
try_files $uri $uri/ @s3 @s3jp;
- ローカルにデータがない場合、@s3 に飛ぶ(USリージョンのs3にリバースプロキシ)
- USリージョンにもデータがない場合は、@s3jpに飛ぶ(JPリージョンのS3にリバースプロキシ)
このような設定をすることで、タイミングで、jp s3にあるか? us s3にあるか特に気にせずデータを取得することができますよね??ね!???