S3を使う時のベストプラクティス(を訳してみた)

記事タイトルとURLをコピーする

最近子どもの水いぼを取る際に、麻酔テープが健康保険適応内である事を知った小室@福岡です。

AWSのドキュメントの一つに、Articles & Tutorialsという物が有ります。これはAWSの中の人、また使っているユーザーがこのように使うといいよ、とAWSをよりよく使える方法を教えてくれる場所です。

サーバーワークスでは、日々のAWSのドキュメントの確認だけではなく、このようなArticles & Tutorialsを読みより深くAWSのサービスについて理解を深めようと個々に担当し、社内発表会を行っています(始めたばかりだけどね!)。

今回私が訳してみたのはこちらです。

Best Practices for Using Amazon S3

この記事は2008年に投稿(更新2009年)されており、現在とは少し違うかもしれませんが、とても参考になりましたので、ご紹介したいと思います。

※これは一般的だろう、というのは除いております。また直訳ではなく、分かりやすく補足をした文章にしております。

  1. アカウント設定方法
  2. バケットのロケーション選択
  3. ケット名とキーの命名規則
  4. データの保護
  5. エラーの処理
  6. PUTとGETのスループット向上
  7. 効果的なオブジェクト削除
  8. 失敗リクエストを減らす
  9. ネットワークパフォーマンスを最適化
  10. その他

 

アカウント設定方法

  • 本番環境でS3を使う場合は、個人のメールアドレスで作ったアカウントは使わない方がよい。
    ※現時点ではバケットの所有者を変更する事が出来ない(解決策としては別バケットにオブジェクト丸ごとコピー)
  • メールアドレスのエイリアスを上手に使って、アカウントのお知らせメールを受け取るべき担当者のメールアドレスが変わっても(担当者変更等)移行出来るように行なう
    ※s3-prod@example.jp -> komuro@example.jpから s3-prod@exmple.jp -> mori@example.jpと簡単に変更が可能。
  • 開発アカウントと本番アカウントを分けて使うとよい
    ※バケットの共有は可能

バケットのロケーション選択

S3にPUTをした際にデータは個々に離れたDCに(オプションにもよるが)3箇所コピーされ成功レスポンスを返すため、遠いリージョンを選んだ場合、レイテンシが発生する可能性があるので、場所は考えた方がよい(日本がメインユーザーであれば東京リージョン、等) 

バケット名とキーの命名規則

バケットでは英数字が基本ではあるが、DNS(<bucketname>.s3.amazonaws.com)としても使われるので、以下を注意する

  • バケットは3-63文字
  • バケットは(一文字以上の)小文字、数字、"."(ドット), "-"(ハイフン)
  • バケットは"."で始まる、終わってはいけない、"-"前後は"."をつなげてはいけない
  • キーは適切にUTF-8にエンコードされたものであればよい。
  • キーの文字列"+"はURLエンコードする
    ※上記以外にも使えなくはないが使わない方がよいものも有るので以下の参考サイトを一読する

参考サイト

 

データの保護

データは複数の通信経路を通る事からデータが損失していたり壊れている事もある為、S3ではデータが壊れていないか、確認をするアルゴリズムを提供している

PUT時

  • PUTでは送ったファイルのMD5チェックサムを確認する
  • S3にリクエストが届いたら、MD5チェックサムが再計算されて比較される
  • マッチしなければ、PUTは失敗する
    PUTでのContent-MD5の利用は必須ではないが、可能ならばAPIを叩く側の実装をする場合、MD5チェックサム機能を取り入れたい(参考: PUT Object
    ※マルチパートアップロード時は分割して送信する為、ETag(Md5ハッシュ)はファイル全体の物とは違うハッシュ値を返却する( 参考: About Etag returned from multipart upload)

GET時

  • GETリクエストでもMD5チェックサムを返却する(ETagがMD5にあたる)
  • クライアント側でもチェックサムを確認する
    ※ブラウザーでGETリクエストをした場合、ブラウザーではMD5チェックサムを提供してないので、使用不可

 

エラーの処理

S3のAPIを呼ぶコードを書いたならば、エラーを処理出来るようにする。以下が発生しうるエラー

400系エラー:リクエスト処理エラー

  • パーミッションが無い、参照しようとしたファイルが無い等
  • クライアント側の時計が間違っている場合(403RequestTimeTooSkewed)もある

500系エラー: リクエストが成功しなかったエラー

  • リクエストが成功しなかった等
  • リクエストの衝突が起こった場合など (参考: TCP/IPプロトコル)
  • 1バケットに、何千ものPUTを突然行なった場合、リクエストに503"Slow Down"エラーが発生する可能性がある
  • ほとんどの500系エラーは再送処理を行なう事で対応が可能

失敗リクエストを減らす

  • PUTやDELETEリクエストをする場合、HEADやLISTをして成功したかどうか調べる必要は無い
    ※PUTやDELETEが成功(200)を返却したら、成功しているので確認しない
  • オブジェクトをアップロード後でメタデータを変更するのではなく、最初のアップロード時に適切な設定を行なっておく
  • アプリ側の実装で可能ならばバケットとキー名をローカルにキャッシュする事を検討する
  • 存在するバケットを何度も確認しない、PUTする前に存在を確認しない
    ※存在しないバケットへのPUTは404"NoSuchBucket"エラーが帰ってくる
  • バケットがあるかどうか確認したい場合は、max-keys-query-stringパラメーターを0にしてListBucketやHEADリクエストを行う。 

          http://bucket.s3.amazonaws.com/?max-keys=0
    
  • S3のバケットをローカルの仮想ドライブにマッピングしている場合は、ウィルススキャンを行なう

 

PUTとGETのスループット向上方法

  • S3では、ストレージの拡張と、負荷の分散を自動で行なっている。
  • 特定のバケットのPUTのパフォーマンスを上げたい場合は、キー名順にすると、各処理の時間が短くなり全体のレスポンスタイムを下げる事が可能になる
  • GETでもソートを行なう事で似た効果を得られる
  • オブジェクトが小さければ、全体のスループットに影響がある
  • 単一のクライアントから複数リクエストを送る場合は、マルチスレッディングで処理を行なう
  • 複数バケットを使う事を検討する。違うアルファベット文字から始めるとよい。
  • 小さい文字数にしたハッシュをキー名の頭に付けると早くなる(数字が良い)
    ※これは例えばtest.pngのハッシュ値が364be8860e8d72b4358b5e88099a935aだった場合、364などをtest.pngに付けてGETを行なうと早くなるらしい(未検証)
     (参考: フォーラム投稿

    $ md5 -s "test.png"
    364be8860e8d72b4358b5e88099a935a
    test.png -> 364/test.png
    例:
     test-2011-3-1.png
     test-2011-4-1.png
     test-2011-5-1.png
    とあった時
     9/test-2011-3-1.png
     f/test-2011-4-1.png
     6/test-2011-5-1.png
    を付けて検索をかけると、早く処理される。プリフィックス(ここでいう9やf,6等)はランダムに有ればよいので、見せかけの英数字(数字がベター)でよいらしい。
    http://ap-northeast.s3.amazonaws.com?prefix=9/swx-fukuoka/test-2011-3-1.png
    http://ap-northeast.s3.amazonaws.com?prefix=f/swx-fukuoka/test-2011-4-1.png
    http://ap-northeast.s3.amazonaws.com?prefix=6/swx-fukuoka/test-2011-3-1.png

参考URL

効果的なオブジェクト削除

  • バケットがバージョニングを有効にしていて、大量のオブジェクトを削除する時はDelete Multiple Objectsを使ってDeleteMarkerマーカーを付ける事で早く簡単に行なえる。
  • 削除したいオブジェクトセットをLISTで呼び出すと削除される(未検証)

ネットワークパフォーマンスを最適化

  • Linuxのカーネルv2.6.8以前、Windows Vista以前の物であればTCP設定を適切に行なう必要がある
  • 接続を使いすぎないようにする。S3は接続を切るまで100リクエストしか受け付けない(接続のリセットがかかる)
    ※80-90リクエスト程度で使い、新しい接続を行なった方が良い
  • もし<bucketname>.s3.amazonaws.com形式で使っている場合は、レスポンスが返るまでにDNS上のリダイレクト(CNAME)が発生しパフォーマンスに影響する可能性があるので使わない方が良い

参考設定

TCP Selective Acknowledgement

その他

  • S3に置くデータは圧縮した方がよい
    http://www.http-compression.com/
  • トラブルシューティング、ヘルプなどはフォーラム、ドキュメントを見る

データを集めるツール等

 

まとめ

  • アカウント周りは、見逃しがちですが、本番環境と検証環境を分ける事で、間違って上書きしたり、流出等を防ぐ第一歩である事を再認識しました。
  • S3の詳細なアーキテクチャは公開されていませんが、例えるならばNoSQLのKVSに近いと言う人がいるのもうなずける内容でした。もう少しS3の構造を知れたら、個々の処理の理由が裏付けられるのになぁとも思いました(Get Objectのprefixは何でランダムでも良いのかが分からなかった)
  • 今回のtipsは大量にファイルを配置、取得する際に有効になりそうな物が多いように感じました。

  • S3は奥が深い!