YAPC::Asia Tokyo 2010 1日目
gihyo.jpさん(http://gihyo.jp/news/report/01/yapcasia2010/0001)さんでのレポートの下書きをおいておきます。
Kazutake Hiramatsuさん「Modern Perl Web Development on Amazon EC2」
- Plackを使ったPSGIなWebアプリの作り方
- Plackについて
- plackupの使い方
- StarmanとStarletの違い
- Starman Graceful restart with HUP (No hutdown with QUIT yet)
- Startlet
- Graceful restart, Graceful Shutdown
- miyagawaさんのwiki
- -LでPlack::Loaderの指定
- Starmanでは-L Delayedを採用
- DelayedとShotgunの番
- Server::Starter
- SIGHUPによるGracefu restartをサポートするサーバプログラム
- plackupをstart_serverで起動するとgraceful restartがサポートされる
- start_serverのintervalオプション。SIGHUPを受け取った後respawnするまでに要する時間(秒)。shutdownに1秒以上かかるサーバの場合この値の調整が必要
- PSGIアプリの書き方
- おすすめモジュール Plack::Request
- リクエストパラメータの取得に仕様
- そのまま使うのではなく、継承して拡張
- Object::Applyというモジュールを使って、flagged utf8へdecodeする
- DBIx::Skinny
- Router::Simple
- URLからコントローラへのディスパッチ
- WEB APIつくるときとか
- JSON::XS
- JSON出力で使う
- daemontoolsを使ったwebサーバの運用
- デーモンを制御するためのツール
- /service配下にサービス用のディレクトリを作成し、直下にrunファイルを置くと、runファイルに書かれたサービスをデーモン化してくれる
- start_serverをdaemontools経由で使用
- コンパイルエラーになるので、src/error.hの書き換えが必要
- svcコマンドがわかれば十分。-u:でサービス起動、-d:サービスの終了 -h:サービスへのSIGHUP送信
- runスクリプトは普通のシェルスクリプト。execでプログラムを起動するのがポイント
- cpanmを使ったCPANモジュールのインストール
- Amazon EC2上でのWebアプリ構築、運用
- Amazon EC2といっても、アプリケーションレベルの構築方法に大きな違いはない
- AmazonEC2のサーバ環境
- Small Instance メモリ1.7G
- CentOS 5.4(32bit)
- DBサーバ
- Large Instance メモリ7G
- 構築に関しての疑問
- サーバのIPアドレス変わるって本当?
- DISK内容が保持されないって本当?
- 負荷分散は?
- アプリケーションのデプロイは?
- サーバのIPアドレス変わるって本当?
- Elastic IPを使って、DNS,Global IPを固定化できる
- 内部からのDNS問い合わせはPrivate IPを返す
- Webサーバに関しては使っていない(オートスケールを使いたいので)
- DISK内容が保持されないって本当?
- インスタンそのTerminateで、破棄される
- EBSかS3を使う
- DBサーバはEBSブートを使ってインスタンスを起動
- 負荷分散は?
- アプリケーションのデプロイは?
- オートスケールを利用していなければ特に困らない
- オートスケールを利用している場合、インスタンスがイメージから起動されるので、元となるイメージを最新化しておく必要がある
- デプロイ方法
- その他の注意点
- amazon EC2でオートスケールを使う場合、IPアドレスが固定化されないので、任意のIPでlisten出来る必要がある
- Amazon EC2の感想
- 本質的な開発作業に大きな差はない
- daemontools + Server::Starter + Starmanで問題なく動いている
- Elastic IPを利用
- オートスケールは便利
- まとめ
- 質疑応答
- Q. daemontoolsのログの保存はどうする?
- A. EBSなりに持っていかないとだめ。
Tokuhiro Matsunoさん 「モダンな Perl5 開発環境について - Modern Perl5 Development Environment - 2010年代を生きのびる Perl5 活用術」
- Perl5をつかったウェブアプリの開発についてがメイン
- Perl5のバージョン
- いままではperl5.8系がメインだった。今は5.12まで出ている。それらの使い分けは?
- system perl sucks。OS標準のperlを使うのは良くないと思っている。コンパイルオプションが一般的すぎる。threadが有効になっているとか。
- ithreads sucks. no "-Dusethreads"。Webアプリケーションを書くときはthreadをoffにしておくほうがよい。これによりインタプリタの速度が15%程度高速化される
- perl 5.10.0は良くない。正規表現使ったときにmemory leakするなどbugがある
- perl 5.x.0は全体的に良くない。
- perl 5.12.2が一番いいと思う
- 安定志向ならperl5.8.9でもよい
- 5.10以降の方がgiven/when, say, smart match, defined or (//), naped captureなど便利な機能が使える。smart matchは速度がでないなど良くない面もあるけど便利。//は地味だけど便利。0とか空文字列に起因するバグが減る。
- perlbrew - 好きなバージョンのperlを使うために
- cpanm
- cpan-outdated
- cpanf
- pm-uninstall
- deployment
- CPANモジュールの選び方
- 8万モジュール以上ある。
- 日付の処理をしよう。'Date'で検索 -> 3000package以上
- 答え「みんながつかってるモジュールをつかう」
- #perl-casual@irc.freenode.org で聞いたら教えてくれる
- Twitterボット @perlism by @lestrrat
- 答え「有名なPerl Hackerがつかってるモジュールを使う」
- Task::BeLike::XXを使う。Task::BeLike::Tokuhirom githubにあります。
- 自分で選ばないといけないとき。http://d.hatena.ne.jp/tokuhirom/20080520/1211292598
- 2004年より前とかはかなり危険なかおり(枯れているものも中にはある)
- Testがこけたまま放置されているのはメンテナンスされていない可能性が高い
- t/以下を見て、テストの充実度を見る
- Dependencies 依存モジュールがみれる。"D"を選ぶと依存しているモジュールも見れるので、どの程度使われているかもわかる
- 有名な作者が作っているモジュールは安心
- まとめ
- みんなで使いやすくしているのでどんどん使いましょう
- Perl is undead!
- 質疑応答
Hiroki DaichiさんInside Mixi - ソーシャルネットワークを支える技術
- mixiについて
- 多様なデバイスに多様なユーザを
- 2000万ユーザ。300億/PV
- mixi development
- 歴史の長いコード
- 機能間連携多い
- テーマ:二つのスケーラビリティ
- Performance : アクセス数の増加や変動に耐える
- Development : 機能追加や他人数開発に耐える
- memcached
- 揮発性KVS
- 汎用キャッシュ機構
- LRU
- 願い事 - memcachedが落ちませんように
- Cacheとは
- 更新に対して、参照が多いデータの参照を高速に
- いつ入れるか、いつ更新されるか
- なにを入れるか
- データ参照のホットスポットを発見して適応
- 通常データ
- keyからketamaで一意のノードから読み書き
- 参照料の多いデータ
- 同時に複数ノードに書き込み。読み込みを分散
- Cache方式 リードスルー
- Cache方式 ライトスルー
- 書き込み時にデータソースとキャッシュに書き込む。
- memcachedは揮発するのでリードスルーと併用が必要。
- 書き込み粒度と読み込み粒度を一致させる必要がある
- Cache方式 変速的なライトスロー
- DBに書き込んでから、マスターを読み出す
- 読み込み時は、リードスルーと同様の実装
- incrをうまく使い数を管理する
- Cache対象レイヤ - カラム単位キャッシュ
- 個別に参照頻度が高いデータ
- get_multiなどで必要なカラムを収集して柔軟に使いたいケース
- set_by_keyなど使えると局所性もコントロールできて高速にできるかもしれないが、利用はしていない
- 削除タイミング。該当カラムが更新。データソース系モジュールで更新
- Cache対象レイヤ - 行単位キャッシュ
- レコード単位でキャッシュ
- 該当レコード更新、データソース系モジュールで更新
- 行単位キャッシュなら、handle socket pluginなどで置き換えたほうがよいかもしれない
- Cache対象レイヤ - ドメイン単位のキャッシュ
- サービス上のモデル分析の妥当性が重要
- 大きすぎる粒度に注意
- その範囲では仕様変更につよい
- Cache対象レイヤ - サービス単位
- 粒度と抽象化
- アクセス数や更新頻度に応じて適切に選択が重要
- memcachedをキャシュ以外に仕様
- リリースの暖めとアクティベーション
- memcached以外のキャッシュ
- コードの複雑さを防ぐ
- コンポーネント間の連携を定義する原則
- 基礎ライブラリ、フレームワーク、サービス、アプリケーションを定義。レイヤ間の依存関係を決定。レイヤごとに品質規準を定める
- システムコンポーネント
- JobQueueサーバを利用してユーザの行動をフック
- シェーピング - 突発的な負荷を緩衝して、スパイクを避ける
- Joinの代替 論理/物理 - 複数ソースにまたがっている関連情報を一貫させる
- 副次的な要件の処理 - 異なる責務領域で必要になる処理
- JobQueueでPublisher-Subscriber
- add_daily日記作成時に、 イベントを作成。関連するモジュールがそれぞれ非同期に処理。
- ModelのCRUDにフック
- 個別コードの事情や構成に詳しくなくても利用できる
- CRUDを補足したサービス
- 日記コメント、日記イイネ!
- まとめ
- 二つのスケーラビリティ
- 両方共最終的には似てくる
- 責務の分散構成と負荷の分散構成は似てくる
Lyo Katoさん「DataPortability and SocialWeb Protocols」
- DataPortability - http://dataportability.org
- apml - ユーザの興味をあ表すマークアップ。スポーツに0.2の興味があるなど。あまり実用的に使われているシーンは見たことがない
- XMPP - Google Talkなどの、メッセンジャーの標準プロトコル
- SocialWeb界隈
- OpenSocial
- OpenGraph - mixiチェックなど
- Activity Stream
- XFN/FOAF
- Others
- OpenID/OAuth
- Access Token
- SGP(Social Graph Provider)が出てきた
- Social Graphの部分をかりてサービスを作る > OpenSocial
- OpenSocial
- 大きく分けて、Gadget APIとRestful APIがある
- opensocial公式ページでPerlライブラリがない
- Net::OpenSocial::Clientを作った。RESTful APIに対応しているところが少ないため、使いどころが少ない。
- OpenIDとOAuthの相違点
- 認可
- Fedaration
- OAuth2.0
- SSL必須(署名がなくなった?)
- session, scopeの標準化
- Request Tokenがなくなった
- Web以外での利用も?
- Profiles
- WebServer Profile - Webを使った3者間の認証
- UserAgent Profile - デスクトップアプリケーションなど
- Username and Password Profile - XAuth
- OAuth::Lite2
- OAuth on Native App
- tips and traps
- UI/UX設計の難しさ
- 実装コスト
- リバースエンジニアリングが必要
- Twitter OAuth事例
- secret埋め込み問題 - OAuth for OpenSource
- サービス間連携 - OAuth Echo
- その他 - XAuth
- OAuth for OpenSocial
- 最初にKeyを与えると、keyとsecretなどが帰ってくる。最初にkeyはsecretがないので詐称される可能性はある
- xAuth
- usernameとpasswordを直接わたして、Access Tokenを返してもらう
- tips
- カスタムURIを使う
- application:handleOpenURL
- Tokenのセキュアな保存
- ローカルマシンへの保存を気をつける
- 暗号化
- アクセスコントロール
- Adobe AIR
- SharedObjectは使わない
- android
- Shared Preference
- Account Manager - OSがアカウント情報を統合管理する仕組みを持っている
- new Contacts API
- まとめ
- OAuthはそろそろ必須技術
- nativeアプリを作るときはいろいろ注意が必要
Jiro Nishiguchiさん「Write Good Parser in Perl」
- パーサとは
- なんらかの意味をもったテキストを、その後の処理に適した形にする
- 「正しく」「動作」して「あたりまえ」という期待
- 重要なのに、空気なような存在
- ベンチはとられまくりでかわいそうな子
- Kind of parser
- Perlでよく使われているパーサ
- HTML::Parser
- Since 1996
- Depended on by 408 modules (HTML::FillInFormなど)
- Written in XS
- 手書き(自前で1バイトずつ進めている
- XML::LibXML
- JSON(::PP)
- JSON::XS
- 高速なJSONパーサ
- 手書き
- HTTP::Paraser::XXS
- Plackで使われている
- Writtern in XS
- 手書き
- Template-Toolkit
- Pure Perl
- Based on Parser::Yapp
- Cache::Memcached
- getコマンドのパーサ (::GetParser, ::GetParserXSもある)
- 手書き
- Why XS?
- How to write - 手書き?
- 自由度は最も高い
- プログラムの腕によっては最高速になることも
- 怠惰なプログラマには向かない
- How to write - 既存モジュールを使う
- 可能な限り新しいフォーマットを作らないのが重要
- 既知のフォーマットを自作するといいことはない。バグを生みやすい
- How to write - 正規表現ベース
- 書き捨てに、小規模に便利
- 十分に速い
- 規模が大きくなってくるとメンテナンスが大変
- Regexp::Assembleを使えばかなり頑張れる
- Parser generatorとは
- Ragel
- Ragel + XS
- ステートマシンの定義を書く
- パースする関数をCセクションに書く
- 分かりやすく宣言的に書ける
- XSいやなんですけど・・・
- データ構造を作って返すだけ
- 文字列結合や配列、ハッシュが触れればOK
- (例)ログ解析
- Benchmark 5倍ぐらい速くなった
- まとめ
- ログ解析などあまり変更しなさそうなものは、パーサジェネレータとXSで高速するといいかも
- 保守性と速度のトレードオフ
Seiji Haradaさん「mixi チェックインの裏側」
- mixiチェックインについて
- スポットの絞り込み方法
- geohashの前方一致。geohashとは緯度経度の範囲を文字列で表す仕組み。
- geohash表現をbase32して、2進化。奇数番目が経度、偶数番目が緯度となる
- geohashが短いと範囲が広がる
- 落とし穴。矩形の端っこの場合。桁数を削って範囲を広げると無駄になるので、周りの部分を矩形をとってきて処理する。
- 高速化
- geohash - 計算処理が多いので早くしたい
- mysqlで無駄なクエリを減らしたい
- 高速化 - Geo::Hash::XS
- Geo::Hash -> Geo::Hash::XS ベンチマークとったら140倍〜200倍速かった
- 隣接するgeoashを求めるadjacentメソッドもある。
- 高速化 - mysql
- キャッシュ化- スポット情報が頻繁に変わらない
- 検索は6文字のgeohash -> 6文字のgeohashをキーにしてMemcachedに積んでいる
- スポットの多い関東と関西をキャッシュ
- まとめ
- 6文字のgeohashによる前方一致で絞り込み
- GPSの精度があがれば7文字もあり
- 最小で1つ、最大で4つのキーで検索
- 検索範囲は半径250mでキーの平均値は2.66個 ( 実機で実際はかったときの最大ズレ幅 )
- 位置情報を楽しもう!
keroyonnさん「非同期タスクの通知処理 with Tatsumaki」
- 月々7000円の小遣いでコツコツと旅費をためてきた
- Web越しにガンガン登録される重いタスクを
- リアルタイムに
- 待ち時間を感じさせずに
- リソースを食いつぶさずに処理したい
- 解決策 - みんな大好きCGI
- クライアント側を非同期化してみる
- multipart/mixed, boundary = "ABC"
- CGI側でboundaryを出力しながらコンテンツを出力する
- クライアントDUI.jsで処理
- 1プロセス1処理なのでC10K問題をもろに受ける
- ストリーミングはC10K問題の影響を受けすぎる
- PSGI/Plackストリーミング
- PPSGI/Plackストリーミングの弱点
- 同期IO処理ができない
- CPU使う処理ができない
- multipart/mixedとか面倒
- 解決策その1 Tastumakiを使う
- 解決策その2 Gearmanを使う
- 重いCPU処理が苦手という欠点を補うジョブキューサーバ
- クライアントからはAnyEvent::Gearman::Clientでブロックしないように
- 解決策その3 WebService::Async
- keroyonnさん作のモジュール
- 非同期処理が簡単に書ける
- まとめ Tatsumaki, Gearman, WebService::Asyncを使えば非同期処理も恐れることはない
吉見 圭司(walf443)さん「Webサービスのページング処理について」
- RDBMSからデータを取得して、それを出す際の話
- ページングとは、1ページに収まらない結果をわけること
- 典型的なやりかた
- 典型的なページング方法 limit 50 offset 10;
- トータル件数はcount文で
- 利点
- たいていの場合に使える
- 欠点
- Group byでうまくいかない
- 時間がかかるクエリの場合の対策
- インデックス効くように
- memcachedでキャッシュ - 結構面倒なことが多い
- 別のやり方
- 次のページがあるかどうかだけを調べる方法
- 1件余分にとれば判断できる。
- perlでページング処理するのはData::Pageが一般的
- 一般的な一番コストがかかるのは、「トータルな件数」を求める処理
- DBIx::Skinny::Pager
- DBIx::Skinnyのsearchを使いつつpagingできる
- DBIx::Skinny::Pager::Logic::xxで拡張できる
- DBIx::Skinny::IteratorとData::Pageを継承してwrapしたオブジェクトを返す
- ページング周りの小技
- データのないページにアクセスしてくるユーザ対策
- あまり軽くできないSQL
- 全文検索ページとかどうしても速度がでないところでは、10000件とか多めに取得しておいて、cacheに突っ込む
- 質疑応答
- Q. ページング処理中にデータが増えた場合表示がずれる可能性があるがどう対処するか
- A. タイムスタンプなどを保持しておいてページングすれば解決できるのでは