fluentdからMongoDBへ連携する際の注意点 #fluentd

fluentdからMongoDBへ連携させる際、はまった所があったので共有しておきます。

【はまった状況】
fluentdは、out_pluginで設定した連携先につなげないときに、バッファファイルとしてローカルにためこむ機能があります。

私の場合、fluent-plugin-mongoを使って、MongoDBへ連携させていたのですが、
バッファファイルが16MBのファイルをMongoDBへ連携させるときに、
以下のエラーが生じ、MongoDBへのInsertが失敗してしまいました。

2011-11-16 16:21:20 +0900: failed to flush the buffer, retrying. error="Exceded maximum insert size of 16,000,000 bytes"
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/mongo-1.4.0/lib/mongo/collection.rb:941:in `insert_documents'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/mongo-1.4.0/lib/mongo/collection.rb:342:in `insert'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluent-plugin-mongo-0.4.0/lib/fluent/plugin/out_mongo.rb:85:in `operate'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluent-plugin-mongo-0.4.0/lib/fluent/plugin/out_mongo.rb:66:in `write'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.7/lib/fluent/buffer.rb:257:in `write_chunk'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.7/lib/fluent/buffer.rb:241:in `pop'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.7/lib/fluent/output.rb:299:in `try_flush'
  2011-11-16 16:21:20 +0900: /usr/local/lib/fluent/ruby/lib/ruby/gems/1.9.1/gems/fluentd-0.10.7/lib/fluent/output.rb:121:in `run'

【原因】
1.MongoDBのドキュメントサイズは、最大で16MB(MongoDBがVer1.8以上の場合)
Documents — MongoDB Manual
2.16MBを超えたドキュメントをInsertしようとした場合、mongo-ruby-driver側でエラーを出力する。
mongo-ruby-driver/collection.rb at master · mongodb/mongo-ruby-driver · GitHub

【対策】
fluentd設定ファイル内の「buffer_chunk_limit(デフォルト16MB)」で、バッファファイルのファイルサイズを変更できます。
この値を変更することで、問題の解決を試みました。

対策1. buffer_chunk_limit=14MB → 失敗
fluentの内部はmsgpack、MongoDBの内部がBSONという形式であるため、
MongoDBへ連携された際に、14MBのバッファファイルであっても、16MB以上に膨らむことがあるとのこと。
#このあたりの詳細は、私も理解が不足している所です><

対策2. buffer_chunk_limit=10MB → 成功
fluentd開発者の@frsyuki さんからの情報により、10MB程度がちょうどよいとのこと。
mongosを落として、fluentdが10MBのバッファファイル×5個をためこんだ状態で、
mongosを起動し、fluentdを再起動()させると、たまったバッファファイルがMongoDBへ格納されました。
mongosを再起動させるだけでは、mongosへ再接続されませんでした。
※[2011/11/23 修正]mongosへの再接続は、fluentdの再起動をせずに行われますが、mongosが落ちている時間が長いとmongosへのリトライ間隔が数分→数時間程度に伸びていくので注意が必要

【結論】
fluentdを使ってMongoDBへ連携するときは、buffer_chunk_limitの設定をお忘れなく!!
※[2011/12/19 修正]
本ブログの問題は、fluent-plugin-mongoのバージョンが0.5.0になって修正されました。
0.5.0以前のfluent-plugin-mongo利用の方は、アップデートをお忘れなく!!
https://github.com/fluent/fluent-plugin-mongo

【謝辞】
情報提供していただいた、 @frsyuki さん、@repeatedly さん、@bibrost さん、@ixixi さん、ありがとうございました。