Upload
hiboma
View
4.175
Download
2
Embed Size (px)
Citation preview
【後半】API 編
GMO Pepabo, Inc. 伊藤洋也
2015/08/29 ペパボテックカンファレンス 第3回 @渋谷セルリアンタワー
MogileFS をバックエンドとしたPrivate S3の作り方
伊藤洋也 @hiboma> GMOペパボ 技術基盤チーム > 低いレイヤの問題解決が好きです
スライドの用語> オブジェクト > 本スライドでは「 mogilefs ストレージに格納されたデータ」を指します
> メタデータ > オブジェクトの名前, サイズ, MIME, 作成日時, ETag … 等 を保持する MySQLのレコードを指します
アジェンダ> S3 互換 API を実装したお話し > 設計に S3 互換を採用するまで > 言語・フレームワークの選定 > 実装 > チューニング小話 > New Relic チラ見
> 所感
(前半のおさらいも含めて) 何が必要なのか?
必要なAPI
必要なAPI
必要なAPI> オブジェクトのGET/PUT/DELETE/HEAD > オブジェクトのリスト取得 > オブジェクトのアクセス権コントロール > 認証 (HMAC認証) > … etc
「Rails で S3 互換 API を実装するぞ!!!!1」
を決めるまで
API 設計
API> どう設計しましょう? > 何で実装しよう? > そもそも作る必要あんの?
設計の選択肢> 新しく API を設計する? > 既存の API を借用する?
新しくAPIを設計する?> 設計するの…やだナー… (本音)
> 会社の基盤となるストレージ の API > 時間に耐えうる設計の重さ
> サーバサイド + クライアントの実装 > PHP, Ruby, ... の実装を全部用意するのは大変だナー > 仕様を社内で流布するのも大変だナー
S3 互換 API ???> 「S3 を作る」じゃ無いよ
> 同じものつくれんわー (棒
> 「mogilefs に S3 と同じインタフェース をかぶせる」
> クライアントから見て S3 と同等に動く事 > 必要な API だけ実装
S3 互換 API > aws-sdk 等, OSSクライアントを利用可能
> ( … な様に作る ) > S3 と合わせてリファレンス実装となる > HMAC認証等、再実装が煩雑なものが揃ってる
> API 実装もいろいろ > とはいえ mogilefs をバックエンドとして流用できるものはさすがに無かった
> 細かい仕様や実装の参考になるものはたくさんある > リクエストパラメータの扱いや、SQLの組み方、エラーで返す XML の組み方等々
S3 互換の制約> S3 API ができる事だけ提供
> 利用サービスに制約が課されることになる > S3 を使うんだ!!! という設計にしてもらえれば
> 利用クライアントの特殊なドメインに閉じた API が増えないという利点はあるかも
> API の 拡張はむずかしそ > SDK の実装をいじっての拡張や改造あれこれは大変そう > SDK v1 -> v2 からのアップデートでごっそり実装が書き換えられたこともある
S3 互換 API の仕様
> REST API のドキュメントが公開されています ! > ここに載ってない挙動は S3 を叩いて確認するか SDK を見るか OSS実装を読んで埋めていく
http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html
さくらさんのオブジェクトストレージ のリファレンス
> さくらさんの「オブジェクトストレージ API リファレンス」を先に読むと S3 互換として最低限必要そうなものが把握しやすい (^^;
http://cloud-news.sakura.ad.jp/wp-content/uploads/2015/01/ObjectStorage_API.pdf
API 実装
API の実装を考える> 何で実装しよう?
> 言語 何にする? > フレームワーク 何にする?
> 条件 > 期限はきびしめプロジェクト > 今後の継続的メンテナンス もちろん必須 > どうやって決めようね?
必須> MogileFS クライアント ★★★ > MySQL クライアント > HTTP のハンドリング > その他
> XML のパース/生成 > HMAC認証の実装で SHA256 であれこれ
既存APIを見直す
既存API perl-Catalyst> perl-Catalyst API の稼働実績がある
> 専用のインターナルな API > ところが、俺俺 API な仕様 > API・DBテーブル設計も S3 仕様とは違う
> Perl で作る? > ペパボで Perl の継続的開発 できるだろうか > 黒田と伊藤は Perl 得意だけど
> 会社全体で見ると … うーん > 別の言語で作りなおしも視野にいれよう
MogileFS クライアント> Perl
> MogileFS::Client > 本家本元。枯れている
> Ruby > mogilefs-client > Unicorn の作者製
> Go > GitHub にいくつか実装落ちてるけどテストが無いとか
> …
mogilefs-client> Unicorn を実装している方が作っている
> mogilefsd を冗長化した場合のラウンドロビン機能、高速に動くような工夫アリ
> MogileFSにコミットもしている > 信頼感高い
> おまけ > Perl のクライアントより遥かに読みやすい (^^; > 黒田 & 伊藤 「perl の MogileFS クライアントはむずかしい 」
フレームワーク> Rails on ペパボ > 社内で Rails を採用しているサービス(リポジトリ) 10~件
> Ruby も含め社内に識者多数 > Rails についての pros / cons は語り尽くされていると思うので割愛
> 運用も枯れている
Rails とパフォーマンス> 30days 用 perl-Catalyst API の実績から Rails で代替可能と判断 > ネットワーク I/O バウンド
> mogilefsd がボトルネック > Rails でも十分に捌けると見込み > スタート時点で扱うオブジェクトのサイズも 1MB未満のものがほとんど
細かい実装
実装の指針> S3をリファレンス実装とする
> S3 へのリクエスト/レスポンスをテスト(request spec) に起こしてから テストドリブンで作ってく
> バグレポートのやり取りが楽
Aさん「S3 に foo bar した結果と Bayt に foo bar した結果が違うんですが?」 私「Bayt が間違っています! 直します!」
認証> HMAC認証 > AWS4-HMAC-SHA256
> 公式ドキュメントでアルゴリズムが公開されているので実装します• http://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4-create-string-to-sign.html
HTTPルーティング
> ドキュメントのを一個一個追って作る > 機能を実装しない API でも 501 Not Implemented を返すようにルーティングだけ作るの大事。漏れがあると別のAPI にルーティングされて意図しない挙動をするケースを生む
スキーマ例
> メタデータの CRUD は1テーブルで実装できる > 一部正規化されていないのは過去の実装を引きずっている
> bucket も DBで扱う複数テーブル実装になるはず
オブジェクトのCRUD> DBのレコードを CRUD + mogilefs で CRUD を1コントーロラ、1トランザクションとして作っていく
> 合わせて S3仕様のレスポンスボディ(XML) や 30X系ステータスを返す実装を埋めていく
> +αで mogilefsd の過負荷に備えてのリトライ実装等 > aws-sdk でリトライが実装されているけど、API でもリトライ
list objects API> オブジェクトの一覧(XML)を返す
list objects API> S3に「ディレクトリ」は無い
> ディレクトリは擬似的に作られているだけ > CommonPrefixes と呼びます
CommonPrefixes の例
CommonPrefixes
> 前方一致の LIKE検索で取り、Rails で文字列加工する
list objects API> 「ディレクトリ」に大量のオブジェクトがある場合の CommonPrefixes をどう作るか?
list objects API> 「ディレクトリ」に大量のオブジェクトがある場合の CommonPrefixes をどう作るか? > クエリを複数回投げる + Railsで文字列加工 > LIKE と NOT LIKE と “>” を組み合わせて途中のレコードをスキップして探索 > 前方一致でインデックス使える > Covering Index の活用
API チューニング
rails-api> rails/all から rails-api でダイエット
> 必要な Rails コンポーネントだけ require する > メモリ(RSS) を小さく
API チューニング> XML の生成がちと遅い > builder, nokogiri, ox で比較
> builder はインデントの有無で速度が結構変わる > 結果、ox がちょっぱやだった
API チューニング> XML のパースがちと遅い > デフォルトは REXML > REXML, ox で比較 > ox がちょっぱやだった
> ( sorry, no benchmark data )
New Relic のメトリクスチラ見
オブジェクトのHEAD > 1
> メタデータを1件SELECT > シンプル > それなりに速い
オブジェクトのGET
> メタデータを1件SELECT + mogilefs 参照 > +100ms ~ > mogilefsd ちょっと遅いですね …
所感
所感 (1)> S3 互換 = 大きな山に見えていたが
> コアな API は 素朴に CRUD + XML をごそごそするだけで作っていける
> バックエンドのストレージによって実装の難易度が変わりそう > 過去の perl-Catalyst API の実績や MogileFS の知見/経験があることで暗黙知で楽ができた部分多数
所感 (2)> もっと高速化したいね > Rails の恩恵を受けている箇所は控えめ
> もっと素朴なフレームワークで小さく・速くなるか?
> mogilefs バウンドをどうするか? > mogilefs をバイバスして DB を直で触る実装
> 他の言語、アーキテクチャ … > golang, …
所感 (3)> このような方向性もありますね
https://speakerdeck.com/naoya/web-api-sabatositefalse-elixir-falseke-neng-xing