the master plan ofscaling a web application
TRANSCRIPT
The master plan of scaling a web application
Yusuke Wada a.k.a yusukebe 2013/10/26
Fukuoka Perl Workshop #24
1
Japan Perl Associationの
講師派遣制度を利用させて来ました
3
自己紹介
•和田裕介 1981年12月23日生
• (株)ワディット代表取締役
• (株)オモロキ取締役兼最高技術責任者
• Webアプリケーションデベロッパー
•物書きも少々…
•独身…
4
どこから来たの?
5
6
すみかは?
7
8
本題の前にYAPC::Asia 2013レポート的な何か
9
YAPC::Aasia 2013 in Tokyo 9月19,20,21日
慶應義塾日吉キャンパス内 協生館
10
概要
•エンジニアのエンジニアによるエンジニアのためのお祭り
•トータル1,131人の参加者
•同時4トラックが走る
11
前夜祭 LTソン::Tiny
13
お祭り雰囲気
14
トーク
15
Perl入学式
16
Lightning Talks
17
オーディエンス
18
Hub
19
引退
20
以上YAPC::Asia 2013ありがとう!
21
さて…
22
本日の題材�「最近なに開発してるか」
23
24
ボケて
•国内最大級のお笑いWebサービス...らしい!
• 3秒で笑えるがコンセプト
•オモロキがコアとなって開発・運営
25
こういうの
26
参考データ
•ほげほげページビュー
•月間お題投稿数3万件
•月間ボケ投稿数120万件
•モバイルアプリは200万インストール
•合計ボケ投稿数1,100万ボケ
27
各種デバイス展開
• PC向けWeb
•スマホ向けWeb
• iOSアプリ
• Androidアプリ
28
外部サービスとの連携
• Yahoo! JAPAN
•百度 hao123
• PlayNow
• goo
• Gunosy
• etc.
29
ボケてセレクト
コラボ・スペシャルアカウント
•島耕作でボケれる!
•企業さんがお題を提供
•ユーザーがボケる
•バナー/告知ページ
•二次利用なども
30
ボケて自体の説明終わり
31
開発の話
32
Bokete versions
• Alpha - リリース前の試験版
• Beta - 2008年8月リリース
• Gamma - 2009年5月リリース
• Delta - 2012年7月リリース
• Epsilon - 次期バージョン
33
全ての開発・運用を一人で担当
34
*モバイルアプリを除く
人的リソースは増やさない
35
便利な外部サービスでスケール
•Amazon Web Services• RDS, ElastiCache, SES ...
• Managedなミドルウェアを選択
• GitHubプライベートレポジトリ
•Travis CI• Uptimer•などなど...
36
ただ、正直しんどい...
37
オモロキ
38
パートナー開発体制
•コア => オモロキ
•アプリ=> オモロキ+ハロ+ブレイブソフト
•コラボ=> オモロキ+ハロ+キャッチボール
• ...
39
ケースによって座組を変える
割り切った分業化を提案
• API Version 2を作成
•ほぼ全機能をWeb APIで提供
•モバイルアプリだけではなくWebでも利用
• Webのフロント部分を誰かに移譲
•言語はなんでもよい!
40
Web API v2
•コアのロジックを全て実装し提供
•既存の仕様を利用する
• JSON-RPC 2.0
• OAuth 2.0
• API <=> Web でネットワークレイテンシ
•割りきって無視をする
41
JSON-RPC
42
# POST to SERVER!{‘jsonrpc’: ‘2.0’, ‘method’: ‘/boke/recent’, ‘params’: {‘limit’: 10}, ‘id’: 1}!!# Response BODY{‘jsonrpc’: ‘2.0’, ‘result’: { entries => […] }, ‘id’: 1}
シンプルなフォーマット POSTでリクエスト
もちろんJSONフォーマット
43
APIの実装
•旧APIと同居させる
•認証認可のためのパス
•情報操作のためのパス
44
アプリ
v1
v2
OAuth
JSON-RPC
方針•既存WAFは使わない => 素Plackアプリ
• OAuth::Lite2 + JSON::RPCを利用
45
./lib/Bokete/WebAPIv2"## Dispatcher.pm"## OAuth/$ "## Controller/$ $ "## OAuth.pm$ $ &## Root.pm$ "## Controller.pm$ "## DataHandler.pm$ &## Dispatcher.pm&## RPC/ "## Dispatcher.pm "## Filter.pm "## Handler/ $ "## Boke.pm $ &## Root.pm "## Handler.pm &## Router.pm
OAuth::Lite2
• Provider実装も含まれている
• mixiでの利用実績あり?
•継承して中身を実装する
• OAuth::Lite2::Server::DataHandler
• code認証、password認証などに対応
46
47
# In your controller!use Plack::Middleware::Auth::OAuth2::ProtectedResurce;!my $middleware = Plack::Middleware::Auth::OAuth2::ProtectedResource->new( data_handler => 'Bokete::WebAPIv2::OAuth::DataHandler', app => sub {},);$middleware->call($self->request->env);!if(my $user_id = $self->req->env->{REMOTE_USER}) { my $user = $self->model('User')->find({ id => $user_id }); $self->stash->{user} = $user;}else{ $self->stash->{user} = undef;}
JSON::RPC
•まかまかさん=>牧さん
•ルータにRouter::Simpleを利用している
48
my $router = Router::Simple;$router->connect( 'get_info' => { handler => 'Hoge::Handler::Root', action => 'get_info'});my $dispatch = JSON::RPC::Dispatch->new( router => $router );...;sub psgi_app { $dispatch->handle_psgi($env);}
API Playground
49
ほぼAPI側のフレームワークは完成!
50
誰かにWebのフロントを担当してもらおう!
51
やまぴー
52
俺「フロントの言語は何でもいいよ」
53
やまぴー「Perlでやります!」
54
俺「!!!」
55
ってことでやまぴーと一緒に
• Boketeのシステム部分をはじめて分業
•マネージメントツールをGitHubに寄せる
•レポジトリ
•イシュー管理
•ドキュメント管理
•積極的に対面して一緒に作業する
•フロントはMojoliciousで実装する
56
Bokete::Front::*•やまぴーが使いやすいフレームワーク作成
57
# presudo code!get '/boke/recent' => sub { my $self = shift; my $result = $self->call_api({ method => '/boke/recent', params => { limit => 10 } }); $self->stash->{entries} = $result->{entries}; $self->render();};
提供するライブラリなど
• Mojoliciousに特化したセッション管理
•認証とAPIのコールをラップするUA
• CSRF対策
•アプリのフレームワーク
58
作法をつくる
例えばセッション管理
59
my $session;!...;!$self->hook( around_dispatch => sub { my ( $next, $c ) =@_; $session = Bokete::Session->new( request => $c->req ); $next->(); $session->finalize( response => $c->res ); });!...;!$self->helper( bokete_session => sub { return $session });
特化したUserAgent
60
my $ua = Bokete::Front::UserAgent->new( client_id => ‘xxxxxx’, client_secret => ‘xxxxxx’, access_token_uri => ‘xxxxxx’, rpc_endpoint_uri => ‘xxxxxx’);!my $token = $ua->get_token({ username => ‘xxxxxx’, password => ‘xxxxxx’});!# OAuthヘッダを設定しつつJSON-RPCをコールするmy $result = $ua->call({ access_token => $token->access_token, method => ‘hello’, params => { message => ‘foo’ }});
今回の構造化のメリット
•テスタビリティが上がる
•分業しやすい、開発者の冗長化
•役割としてのフォーカスが明確になる
•フロントエンドはやまぴー
•ロジックとフレームワークづくりに集中
•他のことに手を付けられる!
61
今後やりたいこと
•インフラ周りの強化
•死活監視・リソース監視・チューニング
•開発・CI環境の整備
•コンテンツデータの解析
•新機能の実験
• Growth Hacks的なこと
62
まとめ
63
今やってるWebアプリの構造化
• HTTPレベルで一つのアプリを切り離す
• APIサーバ
• OAuth認証
• JSON-RPCによる情報操作API
•分業出来てフォーカスが絞れる
•絶賛開発中
•ウマくいけばやれることが広がる! 64
おわり質問等どーぞー
65