fluentd を利用した大規模ウェブサービスのロギング
TRANSCRIPT
fluentd を利用した大規模ウェブサービスの
ロギング
cookpadid:secondlife / @hotchpotch
提供
•id:secondlife•@hotchpotch•舘野祐一 / Yuichi Tateno•Shibuya.js 発起人•Asakusa.rb 所属•fluentd コミッタ̶•BiS, ももいろクローバーZ
仕事•COOKPAD 開発基盤部所属•サービス開発をしやすく=ユーザに価値を届けやすく
•Ruby/Rails のバージョン上げる•ミドルウェアの導入/ライブラリの実装•テスト / CI•デプロイの仕組み
なぜロギング?
なぜロギング?
なぜロギング?
価値 検証
なぜロギング?
価値 検証
なぜロギング?
価値 検証現行いまいち
検証に時間がかかる=
ユーザに価値を届けるのが遅れる
解決すべき仕事
COOKPAD
COOKPAD
1,500万 UU (pc のみ)
110万レシピ
ロギング
PV それ以外
•巨大なデータ•MySQL
•利用方法•バッチで一時集計•中間テーブルに保存
PVログ
•巨大なデータ•MySQL
•利用方法•バッチで一時集計•中間テーブルに保存
PVログ
•オンメモリなら高速•一日分ならオンメモリ•バッチ用DB二台(メモリ32G)•オンメモリでない•遅い
PVログ + MySQL
•保存速度•blackhole + slave で速い•がそれでも詰まる時が
PVログ + MySQL
•データの保持•巨大・直近のデータしか保持できない•今後スケールしない恐れ•過去ログはバックアップ•即座に利用できない•過去データをサービス開発に利用できない
PVログ + MySQL
•MySQL へ
•JSON でシリアライズ•create table
他のログ
•アプリケーションでたくさん記録•insert コスト•もっと手軽に取りたいのに!•データ構造•JSON で入れる -> 集計面倒•create table -> たくさんテーブル…
他のログ+MySQL
•データストレージ•MySQL でない選択肢も
•ログをたくさんとっても重くならない•データ構造•扱いやすいスキーマレス•だけど高速・スケールする
悩み
fluentd
•データストレージ•MySQL でない選択肢も
•ログをたくさんとっても重くならない•データ構造•扱いやすいスキーマレス•だけど高速・スケールする
fluentd
cookpad での構成
•構造化ロガー•安定性•パフォーマンス•プラガブル
fluentd
•MySQL だとカラム追加が必要
•様々な所に気を使う•サービスを落とさない•バッチのコード•みんなログの情報を追加しない
構造化ロガー前
•MySQL だとカラム追加が必要
•様々な所に気を使う•サービスを落とさない•バッチのコード•みんなログの情報を追加しない
構造化ロガー後
解決
•MySQL
•insert コスト•blackhole ストレージエンジンでもネットワークコストがそこそこ
•アプリに気軽にログをしこみすぎると遅く…
パフォーマンス
•fluentd•バッファ + 転送•アプリサーバのローカルに fluentd•定期的に転送•アプリでの処理時間はほぼ0コスト
パフォーマンス
•処理能力•中央の fluentd は1台、1スレッドで十分処理できてる (m1.large)
パフォーマンス
•11月下旬から合計100台弱で運用•本体は安定している•一回だけ古いバージョンで自然死•エラーになるのはプラグイン•対策して pull request
安定性
•buffered•転送先/保存先が落ちてても再送•一時的に数分止めても、ちゃんと再送•保存先 mongodb
•6時間止めても、ちゃんと保存
安定性
•さまざまなInput Plugin•tail / TCP / HTTP etc...•さまざまなOutput Plugin•s3 / mongo / td / hdfs ...
•Rubyで書ける
プラガブル
•PV系のLog•MySQL からの移行検討中
•その他ロギング全部•もうすでに移行•mongodb
fluentd
cookpad での具体的な利用法
•すべてのアプリサーバは td-agent•CentOS なので rpm で
•td-agent は自前のRuby1.9.2入り•構成管理は puppet•基本的に設定ファイルは変わらない
fluentd 構成
<match cookpad.**> type tcp host fluentd-proxy-01 retry_limit 9 <secondary> host fluentd-proxy-02 </secondary></match>
•中央の転送用サーバ•Ruby 1.9.2 (RVM)
•git で設定ファイル管理•Gemfileで各種fluentd/plugin利用
•よく変更するため
fluentd 構成
# Gemfilesource :rubygems
gem "yajl-ruby"gem “bson_ext”gem "fluent-plugin-mongo", :git=>'git://git-01/fluent-plugin-mongo'gem "fluentd", '0.10.8'# ...
$ git pull --rebase$ bundle install$ bundle exec fluentd \ -c fluentd.conf \ -d fluentd.pid \ -o fluentd.log
Rails からの利用class CookpadLogger class RailsLogger < ::Fluent::Logger::TextLogger def initialize(rails_logger) super() @rails_logger = rails_logger end
def post_text(text) @rails_logger. debug("[CookpadLogger]\t" + text) end end
class CookpadLogger def self.create_logger(tag = 'cookpad') case Rails.env when 'production' Fluent::Logger::FluentLogger.new(tag) when 'test' Fluent::Logger::TestLogger.new else RailsLogger.new(Rails.logger) end end
Rails からの利用
it “PVログにユーザの アクセスが記録されていること” log = CookpadLogger.pvlog.queue.last log[:user_id].should == user.id
テスト時
class CookpadLogger module PVLog def post(tag, data) super tag, normalize(data) end def normalize(data); do_something data; end end
def self.pvlog @@pv_log ||= lambda { logger = create_logger ‘cookpad.pvlog’ logger.extend PVLog }.call end
ロガーへの実装追加
Tips•バッファからすぐ処理•$ pkill -USR1 -f fluentd•flush_interval 1s # 設定に•設定ファイルを再読み込み•$ pkill -HUP -f fluentd•(ただしGemfile/ライブラリ更新時はうまくいかない)
嵌ったこと•td-agent の設定ファイルの反映後の再起動漏れ
•初期設定のまま運用してしまった•設定でルーティングにミスっても ”エラーにならない”
•集計時、ちょっと少ないことに気づいて調査
•ngrep で転送されてないサーバが!
こうなったら嬉しいな•fluentd の設定ファイルをもっと柔軟に•今ほぼ全部の plugin を独自 git のレポジトリで管理
•正規表現/フィルター等…•変数等使えないため設定のコピペが…•それ Ruby の DSL で?
ログの重要性•数値は “何が正しいか” の指針に•ログを取る、が fluentd で簡単に•きちんと統計を考えられるエンジニア•巨大データ処理 -> Map/Reduce の出現で簡単に
•どのデータに何の価値があり、それを仕事に結びつけらるか
提供
提供データを通じて料理をより楽しくしていきたいデータマイニングエンジニア
大募集中です!
提供質問?
Rails
AWS MySQLEMRmongodb
サービス開発統計
Rubyfluentd
パフォーマンスmiyagawa