fluentdを多段構成にして、mongodbに出力するところでハマったのでメモ。
上の構成のように、各サーバにfluentd + out_forwardを置き、集約するログサーバにfluentd + out_mongoでmongodbに出力している場合に、上段のfluentdでbuffer_chunk_limitを10mより大きい値にしていると、エラーになることがあります。
まず、out_mongoでbuffer_chunk_limitを10m以内にしないといけない理由は、fluentdからMongoDBへ連携する際の注意点 #fluentdを参考にしてください。
ここで多段構成の場合、上流の buffer_chunk_limitが大きいと上流から大きなサイズのデータの塊が流れてくることがあります。それを受けとったfluentdはそれをそのままoutput pluginに流す実装となっているようです。そのため、末端のout_mongoだけ buffer_chunk_limit 10m としていても、上流から来たデータの塊をそのままmongodbにinsertしようとして、エラーとなるようです。
ちなみにこの場合のエラーメッセージとしては以下のようなものが出てきます。"next retry will be"といってますが、chunkが分割されるわけではないので、永遠に失敗し続けるわけです。
2013-02-22 13:46:56 +0900 [warn]: temporarily failed to flush the buffer, next retry will be at 2013-02-22 13:46:58 +0900. error="Exceded maximum insert size of 16,000,000 bytes" instance=260250280 time=1361508416
対策としては、末端にout_mongo (や、buffer_chunk_limit に制限を加える必要があるplugin)を使う場合、その上流の全てのfluentdでその上限値(out_mongoの場合 10m)に設定する必要がある、ということになりそうです。
設定を修正した後は、mongodbで8000lines/secぐらいまでの性能は確認できました。ちなみにこの時のIOPSが400〜500ぐらいだったので、IO性能はまだまだいけそう。前の記事でmongodbのinsert性能が低いような話を書きましたが、原因は別のところにあったので訂正します。
修正後の設定は以下のようになります。上流のfluentdのbuffer_chunk_limitもきっちり10mにしておきましょう!
- 上流サーバ
<source> type tail format ltsv path /var/log/httpd/access_log.ltsv tag proxy.access_log pos_file /var/tmp/fluent.log.pos </source> <match **> type forward buffer_type memory # buffer_chunk_limit must be under 10m if out_mongo is used in downstream. buffer_chunk_limit 10m buffer_queue_limit 128 flush_interval 1s retry_limit 10 retry_wait 5s send_timeout 5s recover_wait 5s heartbeat_interval 1s phi_threshold 10 hard_timeout 10s <server> host fluentd port 24224 </server> </match>
- ログサーバ
<source> type forward port 24224 bind 0.0.0.0 </source> <match **> type mongo tag_mapped capped capped_size 10m nodes mongod database fluent collection debug buffer_type memory buffer_chunk_limit 10m buffer_queue_limit 1280 flush_interval 1s retry_limit 10 retry_wait 5s </match>