51
【後半】API 編 GMO Pepabo, Inc. 伊藤洋也 2015/08/29 ペパボテックカンファレンス 3@渋谷セルリアンタワー MogileFS をバックエンドとした Private S3の作り方

MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

  • Upload
    hiboma

  • View
    4.175

  • Download
    2

Embed Size (px)

Citation preview

Page 1: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

【後半】API 編

GMO Pepabo, Inc. 伊藤洋也

2015/08/29 ペパボテックカンファレンス 第3回 @渋谷セルリアンタワー

MogileFS をバックエンドとしたPrivate S3の作り方

Page 2: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

伊藤洋也 @hiboma> GMOペパボ 技術基盤チーム > 低いレイヤの問題解決が好きです

Page 3: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

スライドの用語> オブジェクト > 本スライドでは「 mogilefs ストレージに格納されたデータ」を指します

> メタデータ > オブジェクトの名前, サイズ, MIME, 作成日時, ETag … 等 を保持する MySQLのレコードを指します

Page 4: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

アジェンダ> S3 互換 API を実装したお話し > 設計に S3 互換を採用するまで > 言語・フレームワークの選定 > 実装 > チューニング小話 > New Relic チラ見

> 所感

Page 5: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

(前半のおさらいも含めて) 何が必要なのか?

Page 6: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

必要なAPI

Page 7: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

必要なAPI

Page 8: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

必要なAPI> オブジェクトのGET/PUT/DELETE/HEAD > オブジェクトのリスト取得 > オブジェクトのアクセス権コントロール > 認証 (HMAC認証) > … etc

Page 9: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

「Rails で S3 互換 API を実装するぞ!!!!1」

を決めるまで

Page 10: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API 設計

Page 11: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API> どう設計しましょう? > 何で実装しよう? > そもそも作る必要あんの?

Page 12: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

設計の選択肢> 新しく API を設計する? > 既存の API を借用する?

Page 13: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

新しくAPIを設計する?> 設計するの…やだナー… (本音)

> 会社の基盤となるストレージ の API > 時間に耐えうる設計の重さ

> サーバサイド + クライアントの実装 > PHP, Ruby, ... の実装を全部用意するのは大変だナー > 仕様を社内で流布するのも大変だナー

Page 14: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

_人人人人人人_>   <‾Y^Y^Y^Y^Y‾

既存のAPIを借用する?

http://aws.amazon.com/jp/s3/

Page 15: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

S3 互換 API ???> 「S3 を作る」じゃ無いよ

> 同じものつくれんわー (棒

> 「mogilefs に S3 と同じインタフェース をかぶせる」

> クライアントから見て S3 と同等に動く事 > 必要な API だけ実装

Page 16: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

S3 互換 API > aws-sdk 等, OSSクライアントを利用可能

> ( … な様に作る ) > S3 と合わせてリファレンス実装となる > HMAC認証等、再実装が煩雑なものが揃ってる

> API 実装もいろいろ > とはいえ mogilefs をバックエンドとして流用できるものはさすがに無かった

> 細かい仕様や実装の参考になるものはたくさんある > リクエストパラメータの扱いや、SQLの組み方、エラーで返す XML の組み方等々

Page 17: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

S3 互換の制約> S3 API ができる事だけ提供

> 利用サービスに制約が課されることになる > S3 を使うんだ!!! という設計にしてもらえれば

> 利用クライアントの特殊なドメインに閉じた API が増えないという利点はあるかも

> API の 拡張はむずかしそ > SDK の実装をいじっての拡張や改造あれこれは大変そう > SDK v1 -> v2 からのアップデートでごっそり実装が書き換えられたこともある

Page 18: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

S3 互換 API の仕様

> REST API のドキュメントが公開されています ! > ここに載ってない挙動は S3 を叩いて確認するか SDK を見るか OSS実装を読んで埋めていく

http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html

Page 19: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

さくらさんのオブジェクトストレージ のリファレンス

> さくらさんの「オブジェクトストレージ API リファレンス」を先に読むと S3 互換として最低限必要そうなものが把握しやすい (^^;

http://cloud-news.sakura.ad.jp/wp-content/uploads/2015/01/ObjectStorage_API.pdf

Page 20: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API 実装

Page 21: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API の実装を考える> 何で実装しよう?

> 言語 何にする? > フレームワーク 何にする?

> 条件 > 期限はきびしめプロジェクト > 今後の継続的メンテナンス もちろん必須 > どうやって決めようね?

Page 22: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

必須> MogileFS クライアント ★★★ > MySQL クライアント > HTTP のハンドリング > その他

> XML のパース/生成 > HMAC認証の実装で SHA256 であれこれ

Page 23: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

既存APIを見直す

Page 24: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

既存API perl-Catalyst> perl-Catalyst API の稼働実績がある

> 専用のインターナルな API > ところが、俺俺 API な仕様 > API・DBテーブル設計も S3 仕様とは違う

> Perl で作る? > ペパボで Perl の継続的開発 できるだろうか > 黒田と伊藤は Perl 得意だけど

> 会社全体で見ると … うーん > 別の言語で作りなおしも視野にいれよう

Page 25: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

MogileFS クライアント> Perl

> MogileFS::Client > 本家本元。枯れている

> Ruby > mogilefs-client > Unicorn の作者製

> Go > GitHub にいくつか実装落ちてるけどテストが無いとか

> …

Page 26: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

mogilefs-client> Unicorn を実装している方が作っている

> mogilefsd を冗長化した場合のラウンドロビン機能、高速に動くような工夫アリ

> MogileFSにコミットもしている > 信頼感高い

> おまけ > Perl のクライアントより遥かに読みやすい (^^; > 黒田 & 伊藤 「perl の MogileFS クライアントはむずかしい 」

Page 27: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

フレームワーク> Rails on ペパボ > 社内で Rails を採用しているサービス(リポジトリ) 10~件

> Ruby も含め社内に識者多数 > Rails についての pros / cons は語り尽くされていると思うので割愛

> 運用も枯れている

Page 28: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

Rails とパフォーマンス> 30days 用 perl-Catalyst API の実績から Rails で代替可能と判断 > ネットワーク I/O バウンド

> mogilefsd がボトルネック > Rails でも十分に捌けると見込み > スタート時点で扱うオブジェクトのサイズも 1MB未満のものがほとんど

Page 29: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

細かい実装

Page 30: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

実装の指針> S3をリファレンス実装とする

> S3 へのリクエスト/レスポンスをテスト(request spec) に起こしてから テストドリブンで作ってく

> バグレポートのやり取りが楽

Aさん「S3 に foo bar した結果と Bayt に foo bar した結果が違うんですが?」 私「Bayt が間違っています! 直します!」

Page 31: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

認証> HMAC認証 > AWS4-HMAC-SHA256

> 公式ドキュメントでアルゴリズムが公開されているので実装します• http://docs.aws.amazon.com/ja_jp/general/latest/gr/sigv4-create-string-to-sign.html

Page 32: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

HTTPルーティング

> ドキュメントのを一個一個追って作る > 機能を実装しない API でも 501 Not Implemented を返すようにルーティングだけ作るの大事。漏れがあると別のAPI にルーティングされて意図しない挙動をするケースを生む

Page 33: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

スキーマ例

> メタデータの CRUD は1テーブルで実装できる > 一部正規化されていないのは過去の実装を引きずっている

> bucket も DBで扱う複数テーブル実装になるはず

Page 34: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

オブジェクトのCRUD> DBのレコードを CRUD + mogilefs で CRUD を1コントーロラ、1トランザクションとして作っていく

> 合わせて S3仕様のレスポンスボディ(XML) や 30X系ステータスを返す実装を埋めていく

> +αで mogilefsd の過負荷に備えてのリトライ実装等 > aws-sdk でリトライが実装されているけど、API でもリトライ

Page 35: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

list objects API> オブジェクトの一覧(XML)を返す

Page 36: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

list objects API> S3に「ディレクトリ」は無い

> ディレクトリは擬似的に作られているだけ > CommonPrefixes と呼びます

Page 37: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

CommonPrefixes の例

Page 38: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

CommonPrefixes

> 前方一致の LIKE検索で取り、Rails で文字列加工する

Page 39: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

list objects API> 「ディレクトリ」に大量のオブジェクトがある場合の CommonPrefixes をどう作るか?

Page 40: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

list objects API> 「ディレクトリ」に大量のオブジェクトがある場合の CommonPrefixes をどう作るか? > クエリを複数回投げる + Railsで文字列加工 > LIKE と NOT LIKE と “>” を組み合わせて途中のレコードをスキップして探索 > 前方一致でインデックス使える > Covering Index の活用

Page 41: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API チューニング

Page 42: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

rails-api> rails/all から rails-api でダイエット

> 必要な Rails コンポーネントだけ require する > メモリ(RSS) を小さく

Page 43: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API チューニング> XML の生成がちと遅い > builder, nokogiri, ox で比較

> builder はインデントの有無で速度が結構変わる > 結果、ox がちょっぱやだった

Page 44: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

API チューニング> XML のパースがちと遅い > デフォルトは REXML > REXML, ox で比較 > ox がちょっぱやだった

> ( sorry, no benchmark data )

Page 45: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

New Relic のメトリクスチラ見

Page 46: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

オブジェクトのHEAD > 1

> メタデータを1件SELECT > シンプル > それなりに速い

Page 47: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

オブジェクトのGET

> メタデータを1件SELECT + mogilefs 参照 > +100ms ~ > mogilefsd ちょっと遅いですね …

Page 48: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

所感

Page 49: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

所感 (1)> S3 互換 = 大きな山に見えていたが

> コアな API は 素朴に CRUD + XML をごそごそするだけで作っていける

> バックエンドのストレージによって実装の難易度が変わりそう > 過去の perl-Catalyst API の実績や MogileFS の知見/経験があることで暗黙知で楽ができた部分多数

Page 50: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

所感 (2)> もっと高速化したいね > Rails の恩恵を受けている箇所は控えめ

> もっと素朴なフレームワークで小さく・速くなるか?

> mogilefs バウンドをどうするか? > mogilefs をバイバスして DB を直で触る実装

> 他の言語、アーキテクチャ … > golang, …

Page 51: MogileFS をバックエンドとしたPrivate S3の作り方 【後半】API 編

所感 (3)> このような方向性もありますね

https://speakerdeck.com/naoya/web-api-sabatositefalse-elixir-falseke-neng-xing