Figure out!! ドリコムエンジニアブログ

ドリコムエンジニアのブログです

PARTNER'S SITE

DRECOM Co., Ltd.

[Rails] RailsDevCon 2010 で話してきた はてなブックマーク - RailsDevCon 2010 で話してきた
2010/11/22 05:56:12 タグ: event

こんにちは! onk です。

一昨日の 11/20 に RailsDevCon2010 にスピーカーとして参加してきました。場所はオラクル青山センターさん。

聞いていただいた皆さま,ありがとうございました。いやー,30 分も話すの初めてだったので緊張したw 実行委員の皆さまもお疲れさまでした!

プレゼン資料はこちら⇒とあるアプリの開発運用(トラブルシュート)

内容ですが,

ソーシャルならではの負荷分散、インフラ、ログ解析とかが聞けると夢が広がっていいかも。他セッションと絶対かぶらないし。大規模サービス作ろうとしている人にはありがたいと思います。

と @2celeb さんからリクエストがあったので,『聞くだけで運用した気になるソーシャルアプリ』を主題にしました。駆け足でしたが,伝えたいことは盛り込めたかなぁと思います。少しでも参考になれば幸いです。

関連記事

  • RailsDevCon2010
  • Togetter - 「RailsDevCon2010のハッシュタグ(#railsdevcon)のまとめ」
  • RailsDevCon2010に行ってきた - 平凡なエンジニアの独り言
  • Rails Developer Conference2010 聴講記 - TrinityT’s LABO
  • RailsDevCon2010に参加してきました - exdesign
  • Rails Dev Con に行ってきた :: marugoshi.org
  • UKSTUDIO - RailsDevCon2010で話してきました
  • RailsDevCon 2010にてCucumberの始め方の話をしました - moroの日記

以下,twitter での反応と補足

Page 1-6

page 1-6

sasata299タイトル画面ww #RailsDevCon

ikm一瞬見えたロゴがw #railsdevcon

sgtakeru@onk さんのセッション開始 #RailsDevCon

d6rkaiz#RailsDevCon とあるソーシャルアプリの開発運用 @onk さん

DiscoveryCoach3つ目のセッション、とあるアプリの運用開発。 (#railsdevcon live at http://ustre.am/qnNA)

ClockWorkStudioとあるソーシャルゲームの開発運用(トラブルシュート) #RailsDevCon

ikm意外と会場にソーシャルゲームを作った人が少ない #railsdevcon

oukayukaO・N・K! O・N・K!! #railsdevcon

話し始める前にソーシャルゲームを開発したことがある人に挙手してもらったんですがほとんど居ませんでした。遊んでる人で半分ぐらいだったかな。

ロゴはおなじみ http://to-a.ru/ ですね。名付け親は @youthk。

page7-12

page 7-12

sgtakeruソーシャルアプリは、API利用、人口爆発、短納期 #RailsDevCon

DiscoveryCoachまずはソーシャルアプリのAPI利用の話 (#railsdevcon live at http://ustre.am/qnNA)

DiscoveryCoach開発はAPIを使った場合のデバックの仕方が肝。 (#railsdevcon live at http://ustre.am/qnNA)

ar1ハンゲームでけー #RailsDevCon つか、800万人いるのかドリコムのソーシャルゲー.

あ,p11 も p12 もアクティブユーザ数じゃなくて会員数です。念のため。適当にプレスリリースから拾ってきたので半年分ぐらい誤差があると思う。

page 13-18

page 13-18

cesare#RailsDevCon 「大安なのでリリース」w

ikm大安大事 #railsdevcon

agilekawabata大安でリリース #RailsDevCon

ar1大安なのでリリース(w #RailsDevCon

oukayukaソーシャルアプリは2ヶ月でリリースがデフォ #railsdevcon

sgtakeru大安でリリース&バージョンアップ #RailsDevCon

tyabe#RailsDevCon リリース日は大安

adzuki34「大安でリリース」 #RailsDevCon

hs9587#RailsDevCon 「とあるソーシャルアプリの開発運用」 大安なのでリリース

DiscoveryCoach2ヶ月でリリースは想定内。短納期をいかにこなすか。何を犠牲にして何を得るのか。。。が大事。 (#railsdevcon live at http://ustre.am/qnNA)

agilekawabata大安リリース駆動開発だな #RailsDevCon

ClockWorkStudio聴いたこともないgemがズラッと並んでた #RailsDevCon

ikmunicorn+nginx+rails3+ruby1.9.2など、今風の環境 #railsdevcon

oreradioドリコムさんもRedis使ってるのね。 #RailsDevCon

TrinityTミドルウェア、ことごとく最新だ。unicorn2, nginx0.7, Rails3, MySQL5.1, Ruby1.9.2, Redis.... やるなドリコム! #RailsDevCon

HexaRedis 使っているのか。 #RailsDevCon

d6rkaiz#RailsDevCon ドリコムさんでの環境一例 nginx+unicorn+mysql+memcached+redis+rails

「2ヶ月でリリースがデフォ」はさすがに言い過ぎっす……。

ミドルウェアは大体最新に合わせるようにしてますねー。「RailsConf 2010 に合わせてリリースされるだろう」と Rails3 beta で開発した挙句 rc4 の状態で本番投入したりとか,Passenger3 で地雷踏んだりとかしています(

page 19-24

page 19-24

ar1ドリコムのミドルウェア環境のversionはかなりあたらしいので揃えてるな。L5520 x2で32GBメモリの上に仮想化。8つくらいのVM #RailsDevCon

ar1#RailsDevCon リクエスト&レスポンスを確認しろ! HTTPのステータスコードをみろ!

cesare#RailsDevCon 「困ったら TCP まで降りる」基本ですなw

ikm困ったらリクエストとレスポンスを見る。TCPレイヤーで見るのが確実 #railsdevcon

DiscoveryCoachバグで3困ったらTCPレイヤまで降りてパケットを確認しよう。 (#railsdevcon live at http://ustre.am/qnNA)

sgtakeruデバックは、困ったら、request/resonseまでみる。TCPレイヤーまで降りてパケットを見る。 #RailsDevCon

arihhパケット監視マジ重要 #RailsDevCon

takaiTCPじゃなくてHTTPだよね

はい,HTTP でしたごめんなさい!

アプリの中から見ているだけだと oauth や jpmobile の挙動によく泣かされたので,API とやり取りするときは必ず WAF が処理する前の request を眺めるようにしています。

サーバ構成はあくまで基本構成で,本番は web がズラーっと横に並んだり cache や db の slave が並んだりします。

page 25-30

page 25-30

ar1#RailsDevCon Net::HTTPにloggerをしこむ net-http-spy. というかこれがrubyねた最初?

ClockWorkStudionet::httpにloggerをしこむnet-http-spy #RailsDevCon

TokyoIncidentsnet-http-spy #RailsDevCon

DiscoveryCoachかなり具体的ですごい。会場の文字入力のかちゃかちゃという音が今日最大かも。。ww (#railsdevcon live at http://ustre.am/qnNA)

ikmnet-http-spyでNet::HTTPにロガーを仕込む。超便利そう #railsdevcon

TrinityTnet-http-spy tcpflow #RailsDevCon

hs9587#RailsDevCon 「とあるソーシャルアプリの開発運用」 問題発見は request と response を見る、眺めてれば分かる事も多い。 net-http-spy Net::HTTP にログを仕込む

ar1#RailsDevCon tcpflowつかってんのか。。yumとかaptをみたり。gree行きのも見ると。。

d6rkaiz#RailsDevCon tcpflow // tcpdumpの保存しないバージョン

masaki925net-http-spy でTCPパケットロギングしてデバッグ #RailsDevCon

TokyoIncidentstcpflow #RailsDevCon

martinbtt's net-http-spy at master - GitHub ですね。外にアクセスしてるのが一目瞭然で便利なので,僕は .irbrc に

require "net-http-spy"

を書いています。

tcpflow は yum や apt で入れてください。ファイルに落としたいときってそんなに無いので flow で十分なんですよねー。

page 31-36

page 31-36

_shimadaタイトルに反して超実践的で参考になる (#railsdevcon live at http://bit.ly/a480k3

nog凄く具体的な話してるなー。 (#railsdevcon live at http://ustre.am/qnNA)

DiscoveryCoach巨大SNSのアプリだとスモールスタートできない。。。 (#railsdevcon live at http://ustre.am/qnNA)

nogRails1インスタンス200MB?多くね? (#railsdevcon live at http://ustre.am/qnNA)

ar1#RailsDevCon スモールスタートさせてくれない。1ヶ月で30万突破を視野にしておく。10万DAUで 1000万imp/day -> 230imp/s 。Railsは200MB workerだと かけ算で40G.

ar1#RailsDevCon m1.xlargeの限界は2300QPSくらい

ClockWorkStudio230imp/secだった場合の必要なマシンリソースの説明が具体的すぎてすげえ #RailsDevCon

tkawaスモールスタート機能(?)あるといいかも。招待制にするとかすればいいのかな? (#railsdevcon live at http://ustre.am/qnNA)

DiscoveryCoachマシンのスペックまでも。。。もう明日からはじめるソーシャルアプリ的な話ですね。 (#railsdevcon live at http://ustre.am/qnNA)

CPU 使用率はアプリによって違うだろうから,分かりやすくメモリ使用量で表現しています。150MB 超えることもあるので念のため 200 弱と言っておきました!

page 37-42

page 7

ikmデータ量の増加が著しいのでmaster/slave必須 #railsdevcon

sasata299ソーシャルゲームの規模感は凄いなぁー #RailsDevCon

ysakaki@onk の発表実践的で凄いな。こういう話がもっと聞きたい! #RailsDevCon

TokyoIncidentsこのスライドは絶対復習したい #RailsDevCon

ar1#RailsDevCon マイミク村. ともだちコレクションみたいなもの。質問を全て保存するのでしんどい。DBをなんとかする。

shinodoggソーシャルゲームのキャパシティプランニングの話。コレは参考になるなぁ。こういうのを大安の日ドリブンみたいなノリで継続してリリースし続けるのはカッコイイ。 #railsdevcon

DiscoveryCoachDBのmaster/slave分散を考える。 (#railsdevcon live at http://ustre.am/qnNA)

johnsmith0707スケールアウトか。puppetとかもあるように、最近はほんとにスケーラビリティの高さが求められるよね。 #RailsDevCon

ikmmaster/slaveはMasochism #railsdevcon

ar1#RailsDevCon master/slave分散。参照系だったらslaveを見にいく、updateはmasterに、とかはアプリで書く。ライブラリつかってない

_shimadaActiveRecordでmaster/slave分散は難しくない (#railsdevcon live at http://bit.ly/a480k3

  • Revolution On Rails: [PLUGIN RELEASE] ActsAsReadonlyable
  • schoefmax's multi_db at master - GitHub
  • technoweenie's masochism at master - GitHub
  • kovyrin's db-charmer at master - GitHub
  • fiveruns's data_fabric at master - GitHub
  • tchandy's octopus at master - GitHub

DB 切り替えてる部分はどれも 100 行無いぐらいなので読んでみるといいです。使い方じゃなくて中身に言及している記事が増えると世界が面白くなる。

page 43-48

page 43-48

ar1#RailsDevCon JOINできないから、RDB関連は消す。habtmとか。

junyaゲームはEventually Consistentだとまずいデータがほとんどだから面倒くさそうだ。 #RailsDevCon

DiscoveryCoach更新系をmasterに、参照系をslaveにまわしてみたが、ゲームのアプリは更新系が多くて限界がくる。例:体力減る。 (#railsdevcon live at http://ustre.am/qnNA)

TrinityTマスタDBをテーブルごとに分割→has_manyやbelogs_toが使えなくなる→関連はAP側で実装か〜。 凄い試行錯誤だったんだろうな。 #RailsDevCon

すみません見栄張りました。分割はカテゴリごとなので,そのカテゴリ内では JOIN 可能です。なので自分でクエリ投げ直す処理はそんなに発生しないですね。

page 49-54

page 9

ar1#RailsDevCon rails3のshardingにはoctopus. 最近はいいハードなのでscaleupで対応

ikmshardingはdb-charmer, data_fabric, octopus #railsdevcon

hs9587#RailsDevCon 「とあるソーシャルアプリの開発運用」  Sharding 、DB のレプリケーションと分割、そういう gem もある

ar1#RailsDevCon MongoDBにするのは悩み中。AR捨てるのが..

sasata299master-slaveはmasochizm、shardingはoctopusを使ってやってるらしい #RailsDevCon

_shimadaテストデータはfakerで作成 (#railsdevcon live at http://bit.ly/a480k3

agilekawabataテストデータ生成に便利なgem faker #RailsDevCon

oukayuka負荷テスト用のダミーデータを作ってくれるgem > faker #railsdevcon

ClockWorkStudio50万ユーザが3ヶ月遊んだ想定のデータを作成した上でのアクセス負荷試験 #RailsDevCon

DiscoveryCoach負荷テストは50万ユーザが3ヶ月遊んだ想定のデータを作成してm本番想定と同じアクセス負荷をかけて行う。 (#railsdevcon live at http://ustre.am/qnNA)

RailsDevCon負荷テストのためにリリース前に50万ユーザが3ヶ月遊んだ想定のデータを突っ込む。 #RailsDevCon

sasata299"MongoDBを使えば解決するんじゃないか”w #RailsDevCon

ar1#RailsDevCon jmeter + fakerでデータ生成 で、負荷テスト.スループット,DiskIO、コネクション数に注目(webとdb)。

スケールアップで対応できちゃったので,octopus まだ使ってません。でも今使うならコレかなぁと考えています。

MongoDB は試してみたいんですが,Mongo 脳になって綺麗な設計が出来るようになるまでにまた 3 アプリぐらいかかるんだろうな。

負荷テストと監視については YAPC::Asia 2010 での myfinder さんの発表が良かったです。myfinder's blog: YAPC::Asia 2010 でソーシャルアプリのシステム監視運用について Talk してきました

page 55-60

page 55-60

DiscoveryCoach基本、最速でユーザにレスポンスを返す。後は裏で非同期。 (#railsdevcon live at http://ustre.am/qnNA)

ikmTOPへのアクセスをトリガーにして各種ページの準備を事前に実行する、とか #railsdevcon

  • defunkt's resque at master - GitHub
  • collectiveidea's delayed_job at master - GitHub
page 61-66

page 61-66

nogメモ:Resque (#railsdevcon live at http://ustre.am/qnNA)

_shimada非同期処理は Resque。 管理画面あり (#railsdevcon live at http://bit.ly/a480k3

sasata299Resqueで非同期処理をガンガン使ってるみたい。マイページ開いたときにはデータが出来上がってる想定みたいだけど間に合わなかったときはどうするんだろう #RailsDevCon

ar1#RailsDevCon 5秒ルールのせいで、非同期を徹底活用。Resque gemをつかっている。管理画面がいい。バッチ処理も簡単。

ClockWorkStudio非同期実行のgem、rescue。管理画面が便利らしい #RailsDevCon

d6rkaiz#RailsDevCon 非同期で扱うためのgemにresque

ar1#RailsDevCon まとめた処理にactiverecord-importを使っている。

agilekawabata一括insert gem activerecord-import #RailsDevCon

sasata299activerecord-import使うとバルクインサートが楽?へー #RailsDevCon

ClockWorkStudioactiverecord-importでBULK INSERT!! #RailsDevCon

_shimadaResque Scheduler。毎回script/runnerを叩かなくていい (#railsdevcon live at http://bit.ly/a480k3

DiscoveryCoachゆーざーが100万人くらいになると「手抜きかな」と思いながら創った部分が必ず「ボトルネック (#railsdevcon live at http://ustre.am/qnNA)

ikmシビアだ #railsdevcon

oreradioユーザ数数万程度を想定しているコードは全てNG #RailsDevCon

n0tshttps://github.com/zdennis/activerecord-import RT @sasata299: activerecord-import使うとバルクインサートが楽?へー #RailsDevCon

TrinityT「ユーザ数、数万で想定しているコードは全てNG」→バッチで1ユーザあたり1秒かかってたら、一日86400ユーザ分しか処理できない! #RailsDevCon

d6rkaiz#RailsDevCon ユーザ数数万程度のコードは全てNG

  • zdennis's activerecord-import at master - GitHub

そういえば Rails3 から route が Rack に載ったので,sinatra アプリである Resque の管理画面も一緒に動かせるようになりましたね。

page 67-72

page 12

ar1#RailsDevCon GAEの設計の意味がわかってくる(w

ikm巨大SNSのユーザ数で自分の技術力が向上 #railsdevcon

DiscoveryCoach巨大SNSから流れてくるユーザ数はエンジニアの甘えを許さない。 (#railsdevcon live at http://ustre.am/qnNA)

junyaURL設計図って rake routes で間に合う気もする #RailsDevCon

_shimada開発中はER図とURL設計書だけで進める (#railsdevcon live at http://bit.ly/a480k3

ysakaki迷ったらRailsっぽく書く。素晴らしい。 #RailsDevCon

ar1#RailsDevCon PDCAを早くするためドキュメントを削減。図の多用。Railsっぽいコードから外れないようなコード。

hs9587#RailsDevCon 「とあるソーシャルアプリの開発運用」 迷う時間を最小限にする: Railsぽいかどうかを考える

ikmRESTfulっていう前提はあるかなぁ RT @junya: URL設計図って rake routes で間に合う気もする #RailsDevCon

nogソーシャルゲームもこういう観点で見ると面白そうだよなー (#railsdevcon live at http://ustre.am/qnNA)

tkawa「正しくwebアプリを作る」それを「正しく」って言い切るのもなぁw (#railsdevcon live at http://ustre.am/qnNA)

johnsmith0707ペアプロで迷う時間を最小限に #RailsDevCon

DiscoveryCoach短納期に対応するひとつの方法。迷う時間を少なくする。=ペアプロ。そしてRailsっぽいかどうかを思考の指針できるように常に考える。 (#railsdevcon live at http://ustre.am/qnNA)

shinodoggドキュメンテーションなくても、RailsっぽいアプリならER図見りゃわかるし、RestっぽいインタフェースならURL見れば分かる。迷ったらRailsっぽくなってるかどうか。くぅー。シビれる。。 #railsdevcon

負荷対策をすればするほど GAE に近づいていっている気がしたので,なるほどあの制限は正しいなと思えるようになりました。一度しっかり RDBMS で戦うと NoSQL や GAE を使うための意識改革が出来るんじゃないかと思います。

URL 設計書は確かに rake routes と中身は同じなんですが,チーム全員で URL を考えるときに 200 行を超える routes.rb だけだと見通しが悪いので,はじめは Excel でやっています。設計が終わって一通り generate し終えたら routes.rb だけ管理で十分ですねー。

page 73-78

page 73-78

ar1#RailsDevCon Plan (常にかんがえる) Check (かってにデータがあつまってくる) 速度をあげる。

ちなみに,天井からぶら下がってるこのモニタのシステムは『グリゴリ』と言います。旧約聖書偽典『エノク書』 (みんな大好きイーノックさん) に出る堕天使の一団。「見張る者」という意味です。

「ユーザーの動きに応じて、PDCAサイクルを異様なほどの超高速で回すのが、ソーシャルゲームの運営だ」 といった話も紹介しようと思ったんですが残り時間が少なかったのでカット。

page 79-83

page 79-83

ar1#RailsDevCon ログの集約、収集にscribeを使ってる!

ikmscribe+messagepack #railsdevcon

ar1#RailsDevCon scribeにつっこむときにmessage-packで圧縮考えてる。

hs9587#RailsDevCon 「とあるソーシャルアプリの開発運用」 scribe 分散した多数のサーバのログの集約が大変

d6rkaiz#RailsDevCon 一日3gbのlogを見るために scribe -> messagepack にするか検討中?

sasata299複数台に分かれたログの収集はscribe使ってる http://d.hatena.ne.jp/perezvon/20100110/1263120529 #RailsDevCon

masaki925ログ転送ライブラリ scribe; scribeサーバに送っておけばscribe 間で転送・エラーハンドリングしてくれる #RailsDevCon

いじょー

長々と失礼しました。また来年も発表できるよう頑張ります!!

はてなブックマーク - RailsDevCon 2010 で話してきた Tweet

[Ruby] FixtureからFactoryGirlへ はてなブックマーク - FixtureからFactoryGirlへ
2010/05/28 06:03:13 タグ: test / factory_girl

Fixture suck! と言われて久しいですね。こんにちは! onk です。

最近は Rails 3.0 でソーシャルアプリを作っています。で,BDD に RSpec 2.0 & FactoryGirl を使い出したので FactoryGirl についてご紹介。

define

まず,FactoryGirl は ActiveRecord に依存しています。factory の定義は AR のモデル単位。

Factory.define :onk, :class => User do |user|
  user.name  "onk"
  user.email "onk@drecom.co.jp"
end

たとえばこんな感じですね。

create / build

定義した factory を使うときは

Factory.create(:onk)
#=> #<User id: 1, name: "onk", email: "onk@drecom.co.jp", created_at: "2010-05-27 18:59:40", updated_at: "2010-05-27 18:59:40">

とか

Factory.build(:onk)
#=> #<User id: nil, name: "onk", email: "onk@drecom.co.jp", created_at: nil, updated_at: nil>

とかになります。

create だとデータを保存してオブジェクトを返します。build は保存せずに返します。 User.new(params[:user]) みたいなものだと思えば OK。あと Hash だけ欲しいときは

Factory.attributes_for(:onk)
#=> {:email=>"onk@drecom.co.jp", :name=>"onk"}

とします。

なお,factory の定義名=クラス名である場合は :class が省略できます。

Factory.define(:user) do |user|
  user.name "名無しさん"
end

使うときもデフォルトは create なので

Factory(:user)

で呼び出せます。

使い方まとめ
factory を定義する
Factory.define
保存されたオブジェクトを取得する
Factory.create
保存していないオブジェクトを取得する
Factory.build
Hash を取得する
Factory.attributes_for

他にも stub とかありますが,とりあえず以上だけ覚えておけば Fixture っぽく使えるかと思います。

ひとつだけ注意点。define した factory は全て Factory.factories に詰められてるだけなので,全 model で共通の名前空間になっています。 名前の付け方には注意してください。model 名で prefix, suffix を付けると分かりやすいですね。

relationship

+-------------------+
|       User        |
+-------------------+
| PK id      int    |
|    name    string |
+-------------------+
         | (user.id = post.user_id)
+-------------------+
|       Post        |
+-------------------+
| PK id      int    |
| FK user_id int    |
|    body    string |
+-------------------+

のような関連を表したいときは factory 定義の中で保存してしまえば良いです。

まずは has_one 関連の場合。

Factory.define :post do |p|
  p.body "オマエモナー"
end
Factory.define :user do |u|
  u.name "名無しさん"
  u.post Factory(:post)
end

で,:user を生成すると

u = Factory :user
#=> #<User id: 1, name: "名無しさん", email: "sage", created_at: "2010-05-27 19:19:37", updated_at: "2010-05-27 19:19:37">
u.post
#=> #<Post id: 1, user_id: 1, body: "オマエモナー", created_at: "2010-05-27 19:19:21", updated_at: "2010-05-27 19:19:37">

となり,見事に関連が張られています。

ちなみに :user と :post を書く順番を逆にすると

ArgumentError: No such factory: post

と怒られてしまいますので,読み込み順を深く考えたくない場合は {} で囲って遅延評価にしておきます。

Factory.define :user do |u|
  u.name "名無しさん"
  u.post {Factory(:post)}
end

has_many の場合は配列で定義します。

Factory.define :user do |u|
  u.name "名無しさん"
  u.posts {[Factory(:post), Factory(:post), Factory(:post)]}
end
u = Factory :user
u.posts.size #=> 3

関連を非常にすっきり書けますね。これが FactoryGirl の魅力の一つです。

callback

関連を記述しているとき,validate があると結構厄介です。先ほどの

+-------------------+
|       User        |
+-------------------+
| PK id      int    |
|    name    string |
+-------------------+
         | (user.id = post.user_id)
+-------------------+
|       Post        |
+-------------------+
| PK id      int    |
| FK user_id int    |
|    body    string |
+-------------------+

で,Post#user_id に

validates :user_id, :presence => true # 要は not_nil

をかけてるとしましょう。ありがちですね。

先ほどのままの factory 定義

Factory.define :user do |u|
  u.name "名無しさん"
  u.posts {[Factory(:post)]}
end
Factory.define :post do |p|
  p.body "オマエモナー"
end

では,:user を保存するより先に :post を保存することになります。このとき,まだ user_id が入っていないので validation に撥ねられます。

Factory :user
#=> ActiveRecord::RecordInvalid: Validation failed: User can't be blank

factory_girl/proxy/create.rb を読んでみると

class Factory
  class Proxy #:nodoc:
    class Create < Build #:nodoc:
      def result
        run_callbacks(:after_build)
        @instance.save!
        run_callbacks(:after_create)
        @instance
      end
    end
  end
end

となっています。つまり :after_build,:after_create で処理を挟むことができます。

これを使えば,validation に引っかかるようなモデルも上手く書くことができますね。

Factory.define :user do |u|
  u.name "名無しさん"
  u.after_create do |user|
    user.posts = [Factory(:post, :user_id => user.id)]
  end
end
Factory.define :post do |p|
  p.body "オマエモナー"
end
u = Factory :user
#=> #<User id: 1, name: "名無しさん", email: nil, created_at: "2010-05-27 19:42:41", updated_at: "2010-05-27 19:42:41">
u.posts
#=> [#<Post id: 1, user_id: 1, body: "オマエモナー", created_at: "2010-05-27 19:42:41", updated_at: "2010-05-27 19:42:41">]

はい,綺麗に書けました。

あ,Factory(:post, :user_id => user.id) みたいに create 時に外から attribute を渡すこともできます。なので「ちょこっとだけ違うオブジェクトを作りたい」とか言うときはテストの中でさらっと書いちゃえば良いと思います。

Factory(:user, :name => "名も無き冒険者")
#=> #<User id: 2, name: "名も無き冒険者", email: nil, created_at: "2010-05-27 19:44:29", updated_at: "2010-05-27 19:44:29">

sequence

unique 制約かけたいカラムってありますよね。そんなの相手に愚直に factory を数十個作るなんてもったいないです。sequence を使いましょう。

Factory.sequence(:google) do |n|
  "go" + "o" * n + "gle"
end
Factory.next(:google) #=> "google"
Factory.next(:google) #=> "gooogle"
Factory.next(:google) #=> "goooogle"
Factory.next(:google) #=> "gooooogle"

まぁ呼ぶたびにインクリメントするだけなので普通に n 返せば良いです(笑)

Factory.sequence :name do |n|
  "user_#{n}"
end
Factory.define :user, :class => :User do |u|
  u.name {Factory.next(:name)}
end
と sequence と next を使うように定義しておけば
Factory.create(:user)
#=> <User id: 1, name: "user_1", email: nil, created_at: "2010-05-27 19:45:15", updated_at: "2010-05-27 19:45:15">
Factory.create(:user)
#=> <User id: 2, name: "user_2", email: nil, created_at: "2010-05-27 19:45:16", updated_at: "2010-05-27 19:45:16">

となります。

Factory.next を {} と遅延評価にするのを忘れると,常に "user_1" が入っちゃうので気をつけて。

parent

factory の継承もサポートしています。

Factory.define :user do |u|
  u.name "名無しさん"
  u.email "sage"
end
Factory.define(:admin_user, :parent => :user) do |u|
  u.name "名無しさん@FOX★"
end
Factory :admin_user
#=> #<User id: 1, name: "名無しさん@FOX★", email: "sage", created_at: "2010-05-27 19:45:35", updated_at: "2010-05-27 19:45:35">

email が継承されていますね。sequence と parent を上手く使いこなせば,Factory.define はそんなに書かなくても良いはずです。Fixture を使っていたときにカオスになったのを思い出して,最低限の記述にすることを心がけましょう。

Fixture からの概念の変化

sequence や parent で見えてきましたね。Fixture と FactoryGirl では概念がまったく違います。Fixture にはオブジェクトの値を直接記述していました。しかし,FactoryGirl で定義するものはオブジェクトではなく雛型です。使うときに,雛型からオブジェクトを好きなだけ作れば良いのです。

冒頭で記述したような :onk というオブジェクトを定義するのは大きな誤り。オブジェクトを定義してしまうと Fixture と変わらず,管理しづらいものができ上がると感じています。雛型名は単なる :user ですね。他に何か定義するなら上記のような :admin_user や,post の有無で :posted_user を作る場合等がありそうです。

個人的にはなんとなく STI っぽいなと感じました。まぁ model のなかで class 作ってるようなモノなので。

faker との連携

雛型だと見切ったら,FactoryGirl と faker を同時に使うと非常に強力なことにも気づけるかと思います。

Factory.define :user do |u|
  u.name {Faker::Name.name}
  u.email {Faker::Internet.email}
end
Factory :user
#=> #<User id: 1, name: "Garland Keebler", email: "baron@wolff.ca", created_at: "2010-05-27 19:57:09", updated_at: "2010-05-27 19:57:09">
Factory :user
#=> #<User id: 2, name: "Marlee Mosciski Jr.", email: "samanta@emard.uk", created_at: "2010-05-27 19:57:10", updated_at: "2010-05-27 19:57:10">
Factory :user
#=> #<User id: 3, name: "Providenci Fisher", email: "madie_boyer@kochgleichner.us", created_at: "2010-05-27 19:57:11", updated_at: "2010-05-27 19:57:11">

Fixture からの解放は,単に関連記述を簡略化するだけではありません。性質の違う雛型を性質名で定義し,使うときには雛型をもとに好きなようにオブジェクトを作る。それが FactoryGirl の素晴らしい点だと僕は理解しています。

参考 URL

  • thoughtbot's factory_girl at master - GitHub
  • [rails]has_manyなフィクスチャを書くのに疲れたらFactory Girlがオススメ! - func09
  • ヽ( ・∀・)ノくまくまー(2009-12-22) - [test] fixture replacement 決定戦
  • faker
はてなブックマーク - FixtureからFactoryGirlへ Tweet

[MySQL] MySQL のチューニング (ボトルネックの検出) はてなブックマーク - MySQL のチューニング (ボトルネックの検出)
2010/04/01 11:51:33 タグ: mysql / performance

こんにちは! onk です。

SAPさんが各社とも「ソーシャルアプリは負荷対策が大事」って言っていますね。弊社でも mixi アプリ(PC),mixi アプリモバイルをリリースしたときはお祭り状態だったので,ふりかえりも兼ねて MySQL のボトルネックを調べる方法を書いてみました。(幸い,モバゲーオープンゲームのリリース時はこれらの経験が役に立ったので何ともなかったです)

といっても 9 割方

  • そもそもサーバの設定がおかしい
  • 更新が多いテーブルなのに MyISAM エンジン
  • for 文の中でクエリを発行
  • INDEX 張ってない
  • データ量がえらいことになってる

辺りなんですけどねー。

基本は下から

まず,ボトルネックを調べるときは下の層から上がっていくのが基本です。たぶん。

なので ssh でサーバに入って (LoadAverage 300 ぐらいまでならなんとか入れますね) 以下のコマンドをよく叩きます。

top

現在稼動しているプロセスの一覧と,システム情報の概要が表示されるプログラム。

見るのは主に

  • Load Average
  • CPU 使用率
  • メモリ使用量
  • swap 使用量

と,これらが異常なプロセス。

たとえば swap だと,正常なときは

Swap:  7879872k total,      764k used,  7879108k free,  3589852k cached

ですが,異常に減っているときは

Swap:  7879872k total,  2529080k used,  5350792k free,  1574320k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
26945 mysql 20 0 7681m 6.0g 5080 S 37 77.2 17214:10 /usr/local/mysql/libexec/mysqld

のようになります。明らかに mysql がメモリ食い潰してますね。free や ps でも確認出来ますが,どのプロセスが悪いのか見渡しやすいので,僕は top が好きです。

vmstat

これもシステム情報を表示するプログラムです。

  • swap が発生しているかどうか
  • CPU 使用率が異常な値じゃないか
  • CPU IO Wait が発生しているかどうか
  • Disk IO が異常値じゃないか
  • Context Switch が異常に頻繁だったりしないか

あたりを確認します。

たとえば CPU IO wait が異常なときは

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
0 11 20092 281480 12 7671592 0 0 27820 42 1967 2557 3 3 41 52
0 12 20092 284492 12 7668020 0 0 26512 1 1812 2222 2 3 47 48
0 13 20092 281188 12 7671080 0 0 33144 0 1890 2258 2 2 40 56
0 13 20092 277208 12 7674300 0 0 24612 0 1722 2000 2 1 38 59
0 24 20092 283364 12 7665688 0 0 24304 0 1871 2287 2 2 30 66
2 21 20092 284912 12 7661960 0 0 31688 30 1714 2130 3 3 35 60

となります。

大抵の場合,以上の 2 コマンドで原因となっているプロセスを特定できるので,新機能のリリース時は 2 画面開いて

  • top -d 5
  • vmstat 5

として見張っています。

ありがちな例

CPU Usage が高い

大概,インデックスの張り忘れです。インデックスさえ張っておけば一瞬で終わるはずの WHERE 句や ORDER 句を,必死に CPU が計算しています。

最初はデータ量が少なくて気づかないかもしれないけど,次第に CPU 使用率が 100% に限りなく近づいて……。

varchar カラムに対して int を検索条件にする場合は INDEX が使われないので注意してください。MySQL は文字列の型に対して where hoge = 1 と絞り込むとき,'01' や '1.00' の行もマッチします。つまり INDEX は使えず,全件走査となります。

ソーシャルアプリでは opensocial_owner_id が文字列なのでコレやりがちなんですよね。さすがにすぐ気づくとは思いますが(笑)

CPU IO Wait が高い

データ量に対して,メモリの割り当てが少ない場合とか。

show table status;

したときの Data_length + Index_length と key_buffer_size や innodb_buffer_pool_size を見直してみてください。せめて Index だけでもメモリに載せてあげたいので。

ディスクの読み書きはメモリの読み書きの 10 万倍遅いです。ディスクアクセスは 1 回につき 5ms 程度かかるので,秒間 200 回しかアクセスできません。

1 回のクエリで 4 回ディスクへのアクセスが発生し,1 ページ表示するのに 5 回クエリを投げるとすると秒間 10 PV しか耐えられないことになります。1 ユーザあたり 150 PV/day,ピーク時に平均の 2 倍になる場合で 2,500 UU/day が限界な感じですね。これが全てメモリに載っていれば 5 億人までいけます。

実行中のクエリを確認

MySQL の設定ではなくクエリが原因だと判断したら,実行中のクエリを確認します。

  • innotop
  • show processlist
  • mprofile

の 3 パターンかな。

innotop

InnoDB を使ってるときはぜひ。innotop - Project Hosting on Google Code

僕が注意しているのは

  • InnoDB Buffers
    • Hit Rate
  • Command Summary
    • Com_select
    • Com_show_status
    • Com_begin
    • Com_commit
    • Com_update
    • Com_insert
  • InnoDB I/O Info
    • Reads/Sec
    • Writes/Sec
  • Query List

ですね。

トランザクションが重い場合,Query List には「COMMIT;」しか表示されなかったりするので注意してください。

show processlist

innotop や mytop で実行中のクエリのリストが見えるんですが,これらを入れていない場合は show processlist; で確認します。

クエリを全て Info カラムに出力したいときは

show full processlist;
mprofile

Kazuho@Cybozu Labs: MySQL のボトルネックを統計的に監視・解析する方法

show processlist を 1,000 回実行し,どのクエリが何回表示されたかの統計を取ってくれます。何から潰すべきなのかの判断に迷ったらとりあえず統計取りましょう。

奥さんも書いてますが,定期的に実行してログを残しておくと,ユーザの動向と DB の使われ方の変遷が見えてきてサーバ増強計画を作りやすいですね。

……思ってたより長くなったので次回 EXPLAIN 編に続きます。乞うご期待!

はてなブックマーク - MySQL のチューニング (ボトルネックの検出) Tweet

[PHP] 第50回PHP勉強会に参加してきた はてなブックマーク - 第50回PHP勉強会に参加してきた
2010/02/24 08:17:30 タグ: event / opensocial

こんにちは!onk です。

第50回PHP勉強会@関東 に参加してきました。会場は 株式会社コンテンツワン さん。50人超のメンバーを入れられる会場って限られてるのですごく助かります。ありがとうございました!

以下,当日のメモです。

mixiアプリについて @weboo

mixi アプリの概要説明。技術的な説明の部分はほぼ mixi Developer Center のままかな。

流行るアプリの例として弊社の ハッピーアクアリウム を紹介いただきました。ありがとうございます^^

mixi アプリの流行るポイント 4 つ

  • 分かりやすさ
  • ソーシャル性
  • 巻き込み性
  • 継続性

はすごく分かりやすい指標。合わせて mixi のソーシャルグラフ (他社と違いバーチャルグラフ化していないリアルな友達) の健全性を保つことに言及されていたのが印象に残りました。

PHPでWEB開発を行うようにしてオープンソーシャルアプリを作る @KuniTsuji

僕らは既に mixi / モバゲーに対してアプリを提供しているので,この辺は実装済みですね。開発時はほとんどソーシャルアプリという意識はないです。

PC と mobile で同じテンプレートを使うのを断念されてましたが,ちょこっと js で加工してあげれば HTML 断片返さなくても大丈夫じゃないかな。

  • HTML のコンテンツ部分に div 1 個カマしておく
  • リンクやフォームの onclick で gadgets.io.makeRequest する
  • callback 内で,取ってきた HTML からコンテンツ部分を取得,wapper の innerHTML を置き換え

カヤックさんの mist.js が参考になると思う。

まぁ実際は PC と mobile では情報量も変わるしページ遷移も変えるしで,とりあえず PC でも操作可能にしておくか程度にしか使えないんだけど。

運用した気になるモバイルオープンソーシャル @cocoitiban

超共感した!!!!

さすがに LA 4 桁はまだお目にかかったことがないなぁw 画像生成怖いっす><

「愛され系ゆるふわコーディング」の重要性はホントに声を大にして言いたいですね。

他サービスの API が落ちているときに

  • 使わなくてもプレイに支障を来さないならそのまま進める
  • でなければ適切なエラーページを返す

のいずれかはやっておきましょう,アプリとして想定しているエラーのはずなので。後でサービス落ちたりユーザの問い合わせが爆発したりと泣きを見ます。

もうホント正しく作るっていうそれだけなんだけどね……。甘えが残っているとそこがボトルネックとなるのを日々実感してます。

懇親会

LT しました! 資料はこちら → ハッピーアクアリウム裏話 (2010/02/22@第50回PHP勉強会)

懇親会ではだいたい @cloned と @cocoitiban,@weboo と話してました。DeNA や mixi との NDA 気にしなくて良いメンツだと話しやすくていっすねw

モバゲーの API についてとか,各コンテナに対して絵文字をどう返すかとか,OAuth 署名の signature についてとか。SAP や Container のエンジニア同士で情報交換出来るのはとても助かるなー。

EC2 どうよ?という話もしたんだけど,正直 200msec 程度の遅延はモバイルだとそもそも回線が不安定なため気にならないかな。サービス投入直後の「どんだけ人が来るか読めない」段階ではクラウドを選択肢に入れない理由がない。伸びが予想出来るようになったら自社サーバに移せば良いです。

というわけで普段からスケールアウト可能な作りにしておくのがソーシャルアプリでは必須。

でも数十万ユーザ&初めの数ヶ月なら,数台でなんとかなります(

雑感

50 回も勉強会を続けるって強いなぁ。PHP 界隈元気ですねー。Symfony 2.0 の楽しげな話も聞こえてきました。

あと,OpenSocial への期待も大きいですね。

cloned さんの

過去のファミコンのような魅力的なプラットフォームなので、同じような感じのアプリがあるからとたじろぐのではなく「うちのはここが良い」というアプリをどんどん開発して公開するのがよろしいと思う。あれだけ素晴らしいドラゴンクエストとファイナルファンタジーがあったにも関わらずたくさんの後続のRPGがヒットして今でも愛されているように。

【第50回PHP勉強会に参加してオープンソーシャルに思うことなど - cloned.log】

という発言はとても共感。ホントに 10 年に 1 度の面白い時代なので,みんなで盛り上げていきたいと感じてます。

はてなブックマーク - 第50回PHP勉強会に参加してきた Tweet

    最新記事一覧

  • RailsDevCon 2010 ...
  • FixtureからFactoryG...
  • 第50回PHP勉強会に参加してきた
  • MySQL のチューニング (ボト...
  • もっと見る

    最新のコメント

    Ruby

  • FixtureからFactoryG...
  • もっと見る

    Rails

  • RailsDevCon 2010 ...
  • もっと見る

    PHP

  • 第50回PHP勉強会に参加してきた
  • もっと見る

    MySQL

  • MySQL のチューニング (ボト...
  • もっと見る

    Mobile

  • もっと見る

    Mac

  • もっと見る

    UI

  • もっと見る

    Tips

  • もっと見る

    お知らせ

  • もっと見る
  • 会社概要
  • プライバシーポリシー
  • 【PR】アルバイトEX

©Drecom Co., Ltd. All Rights Reserved.