0

Mobage運用技術勉強会に行ってきた

Web公開制限が無いらしいので、殴り書いたメモを貼り付けておく。


謎のアルゴリズムで集められたはてなユーザーに、モバゲーの運用技術を惜しげもなく教える勉強会に行ってきた。
インフラもPerlも全然わかんないんだけど何故誘われたのか謎。


モバゲーすごい・・・台風激しかったけど行ってきて良かった。特にモニタリング手法が面白くて、一瞬だけ全プロセスにデバッガをアタッチして待機状態のプロセス数を調べるとか、DBバックアップサーバーの遅延を監視してるとSlaveへの遅延発生が予測できるとか。頭いい。
たぶんMobageを支える技術に書いてある内容の一部だと思われるので、本も買ってみる。

あと社食で閉店前に「モバゲ〜」って歌が流れててわかめ高校みたいで面白かった。


2012年6月19日 @ DeNA


  • 渋谷ヒカリエの21階
  • 台風きてるからヤバかったらすぐ帰りましょう

インフラ部門紹介(小野氏)


  • 世界展開
    • mobage(アメリカ)
    • mobage(日本)
    • Daum mobage(韓国)
    • mobage なんとか宝谷(中国)(読めない)
  • Rackspace、AmazonEC2を使用
  • インフラも運用だけじゃなく開発する
    • Handler socket plugin
    • MySQL-MHA
  • 非富豪的感覚
    • 古株が多いのでこだわる
    • サーバー台数少ない
    • G社の半分ぐらい

運用技術 Web編(樋口氏)


  • ケチなのでサーバー台数少ない
  • webサーバーの資源管理
    • FastCGI
    • デバッガ
    • 障害調査
  • 全体構成
    • 基本的にLAMP
    • FW/LB
    • Webサーバ・DBに大別
    • Apache+FastCGI
  • 一枚岩アプリ
    • ゲーム・掲示板・コミュニティ全て同じアプリとして動作
    • ゲームごとに別ではない
    • メリット
    • ゲーム間の連携が容易
    • サードパーティのOpenPlatform使ったゲームはMobageと呼んでない
  • Webサーバ機はCPUやメモリがネック
    • Mobageの全機能をloadするとメモリ1GB使う
    • 全pmファイル読むだけで1GB
    • メモリ使用量を抑えてワーカープロセス数を増やしたい
    • 工夫する
    • サーバー1台あたり100プロセスぐらい動いている
  • FastCGIワーカー数
    • IO待ちでsleepしているのでCPU数の2,3倍起動する
    • プロセス数が多いほど耐障害性高い
    • バックエンドDBが詰まった時に影響が少なくなるので
  • ワーカープロセス数の空きを調べる
    • あと何%空いてるか?
    • 走っているプロセスにデバッガをアタッチ、スタックトレース取ってすぐデタッチ
    • リクエスト受付状態にあるプロセス数を数えればわかる
  • bulkdbg
    • 複数プロセスのスタックトレースを高速に取得
    • gdbより速い
    • シンボル解決のタイミングがgdbと違うらしい
    • 複数プロセスなのでライブラリ同じ、無駄なので読まない
    • 5秒ごとに実行している
    • オーバーヘッドほとんど無い
  • gdbperl.pl
    • Perlのスタックトレースをとる
    • 内部でgdbを使ってPerlインタプリタの内部変数を読む
  • どっちも実サービスで使っている
    • 問題起きたこと無し
  • 障害調査の手法
    • gdbperl.plをアタッチ
    • straceをアタッチ
    • bulkdbgでモニタリング
    • NYTProfでプロファイルデータ取得
    • DBのログ
  • メモリ利用効率化
    • メモリに全部読むと1GB
    • 特定のゲームだけならそんなに行かない
    • サーバをグループにわける
    • Perlモジュールプリロード
    • OSページキャッシュ
  • 昔のMobage
    • ワーカーをforkさせておく、それぞれPerlをexec、モジュール読み込みリクエスト処理
  • 最近のMobage
    • fork前にモジュール読み込む、その後ワーカーをfork
    • メモリ節約できる
    • Linuxだと、forkしたプロセスのメモリ領域は書き込まない限り同じ場所を参照する
    • 慎重に移行した
    • socketを開いた状態でforkすると問題が起こる事がある
    • 移行後、メモリ使用量半分になった
  • ページキャッシュの効率化
    • アプリのログがキャッシュされる
    • swapする
    • posix_fadvise(POSIX_FADV_DONTNEED)
    • ファイルをページキャッシュに載せなくする
    • 10秒ごとにログファイルをページキャッシュから追い出す

運用技術 DB編(岩永氏)


  • サーバー多い
  • データでかい
  • トラフィック多い
  • DB
    • Master/Slaveレプリケーション
    • 更新系クエリはMasterに
    • それ以外はSlaveへ
    • Masterへの書き込みがSlaveに即コピーされるわけではない
    • 課金系とかはMasterへ
  • 最初
    • 1データベースに全テーブル入れてた
    • 即あふれた
  • テーブル分割
    • JOIN基本的に使わない方針
  • レコード単位のsharding
    • 分散方法
    • consistent hashingみたいにクライアントサイドで参照先を計算
    • mapping table
    • 参照先が別のところに書いてある
    • mapping tableの方が最近はよく使っている
    • consistent hashingだと2→4→8→16..としか増やせないから無駄が多い
    • map先はmemcachedやアプリ内にキャッシュしておく
    • 両方使っている
    • 全shardを見ないとならないような機能は、基本的にゲームに付けないようにしてもらう
  • auto increment
    • MyISAMのDBを使う
    • SELECT LAST_INSERT_ID()
  • scale back
    • スケールアウトの逆
    • DBをわけちゃったのを集約したい
    • 1台でmysqldを複数起動
    • 1台に仮想IPを複数ふる
    • my.cnfのbind-addressでmysqld複数に振り分ける
    • アプリ側からは今までどおり、複数台のサーバーに分散されているように見える
  • バックアップ
    • サービスに入っていないslaveがいる
    • Master障害時にMasterになる
    • 朝3時にmysqldumpで論理バックアップ
    • バックアップがあると、slaveの追加が容易
  • MHA
    • MySQL Master High Availability
    • バックアップ等の自動化ツール
    • Masterのスキーマの更新にも使える
    • 先にSlaveのスキーマ更新しておいて、最後にMHAでMasterを切り替えるらしい
  • Purge
    • MySQL5.1以前
    • DELETE使うしかない
    • 5.1以降
    • パーティショニングが使える
    • droptable並の速度で消える
    • RANGEパーティションで日付で消せる
  • トラフィック多い
    • indexはった順番を意識してSQL書け
    • 全スキャンしないでほしい
  • ほとんどはプライマリキーで読むことが多い
    • Handler Socket Pluginを使う
    • Memcachedよりも速いというベンチマークもある
    • 元々はMemcachedでやってた
    • MySQLとMemcachedのデータの一貫性を確保するのが面倒だった
    • Handler Socketに一本化
  • updateクエリが多い時
    • SINが落ちる
    • デッドロック
    • DB lockすると他リクエストが困る
    • まず先にアプリからDBにつないで、lockする時間を最小限にするようにコード書く
    • デッドロックしないようにクエリの順番を工夫する
    • 楽観的ロック
  • モニタリング
    • バックアップサーバーの遅延を見る
    • 近いうちにSlaveにも遅延が来る、と予想できる
    • 先読みしてチューニングする
  • SSD使う
    • HDDだと間に合わない時はSSD
    • PCI ExpressのSSDは速いけど高い、まだあまりつかってない
    • SATA SSDを使っている

0

ネタ画像検索No.1 tiqav.com のrubygemとか作った

レス画像検索No.1/画像会話なら ちくわぶ


インストール

gem install tiqav


画像を検索、保存

require 'rubygems'
require 'tiqav'

## 検索
images = Tiqav.search 'ちくわ'

images.each do |img|
puts "(id:#{img.id}) #{img.permalink} => #{img.url}"
## 全部保存する
img.save(img.filename)
puts "saved!! => #{img.filename}"
end

## ランダム
img = Tiqav.random
puts img.url
puts img.thumbnail
puts img.glitch


## 幸運
puts Tiqav.feeling_lucky 'ちくわ'

最初はスクレイピングで実装した。
v0.0.1を公開して寝て起きたらseiryoさんがJSON APIを作ってくれてpull requestくれてた。
ありがとうございます。

githubにソースコードおいてある。 https://github.com/shokai/ruby-tiqav


おでん

tiqavの画像検索結果からランダムに画像を入れるサービスを作った。HTMLでスライド作るのに便利だと思う。
http://oden.herokuapp.com/

こういう風に埋め込むと
<img src="http://oden.herokuapp.com/あきらめ.jpg">
リロードする毎にランダムな画像がでる。


githubにソースコードある https://github.com/shokai/oden

0

ruby1.9の関数を1.8.7で使う

backports使ったら1.8で1.9の関数が使えるようになる。
https://github.com/marcandre/backports


requireしておくだけでいい。

require 'backports'

最近Heroku使い始めた関係で、ようやくRuby1.9.2を使い始めた。

1.8のArray#choiceという配列の中からランダムに要素を取り出す関数が、1.9ではArray#sampleになっていたりとか、違いがある。backports読み込んだら、Array#sampleって書いておけば1.8/1.9両方で動く。

0

sinatra-contrib

sinatra-content-forの0.2がrubygemsから消えた。
どこ行ってしまったのかと思ったら
https://github.com/sinatra/sinatra-contrib
最新版はsinatra-contribに移動してた。

インストールして

gem install sinatra-contrib

いつも通り使える。
require 'sinatra/content_for'

sinatra-reloaderもsinatra-contribに入ってた。

0

プログラムの写経

プログラミング初心者が写経する時に気をつけると良い事を4つ説明します。


画像はイメージです
IMG_0441

プログラムを勉強する時に、写経しろ(すでに完成しているプログラムを本から書き写せ)とか言われるが、ちょっと意識するとだいぶ違うと思う

1. 外から書け


例えば、1からnまでの数字を全部表示するプログラムがあるとする。
def run(max)
1.upto(max).each do |i|
puts i
end
end

run(10)


これを写経する時、上から下に1行目から順に書くのではなくて、まず
def run(max)
end

いちばん外側を書いて

def run(max)
1.upto(max).each do |i|
end
end

中を書いて

def run(max)
1.upto(max).each do |i|
puts i
end
end

こうなる。


上から書かないのが重要。プログラムは普通は外から書くものなので。
俺は今までに200人ぐらいはプログラミング初心者にコード書くのを教えた事があるんだけど、まず最初に直してもらうのはこれです。


2. 処理される順番に書け

上の「1〜nの数字を表示する」例では、先にdef runの関数を書いてしまってるけど


まずはこれを書く
run(100)


次にdef runの部品を書く。
def run(max)
end

run(100)

コンピュータが実行される順に書いた方がいいですね。
先に下にrun(100)を書いておけば、実行できるから。

def runの中身を1行書く毎に実行できるので、文法の間違いもすぐ気付ける。
puts i が無い状態で実行しても画面には何も表示されない。でも実行してみれば文法にエラーがあるかはわかる。
たくさん書いてから最後にrun(100)を書いて、たくさんエラーがでると精神的にダメージがでかい。

プログラミングの初心者は、とにかく全部完成してから実行して、エラーが10個ぐらいでて助けを求めてくるんだけどこまめに実行した方が良いし、こまめに実行できるような順番でコード書いたほうが良い。


3. エラーでググれ

プログラムを書いているとエラーがでますが
1to100.rb:3:in `
': undefined method `run'
とりあえず英語を読むと良い。それでも意味がわからなかったら”ruby undefined method”とかでググる。

みんな大学受験をして入学したはずなのに、どういうわけか黒い画面に白文字で英語が表示されると一切読まなくなる。
たぶんどの部分がエラーなのかわかりにくいのが悪いんだけど。

Railsとかだと、たくさんのクラス間で関数を呼びあってるから物凄い行数のエラーが表示されて、どこ読めばいいのかわからないからしょうがない
Javaならエラーを日本語で出すように設定してあげると読むようになる。


4. うまい人の作業を見る

ライブコーディングというやつなのですが、1からコード書いていってエラーに試行錯誤して動くところまで、うまく書ける人がやってるのを見ると良い。
どういう順番で書いたり考えたりしてるかがわかると思う。


SFCだと、学部のころに履修した萩野先生のシステムプログラミングという授業が良かった。毎週課題が出て1週間悩むんだけど、次の授業で萩野先生が凄い勢いで答えを実装してくれる。かっこいい。
あとmyatsumotoは洛西さんがJavaScriptをライブコーディングしてるのを見て覚醒したみたいな事言ってた。

ポイントは、プログラム書くのがウマイ人のプログラムもエラーがでるということです。うまい人でもスペルミスやカッコのとじ忘れとかするんだけど、そういうのを見つけて直していくのを見せてもらうと勉強になると思います。