fluentdのbuffer周りで注意すべき点

#topic
- buffering parameters
- flushing parameters
- retries parameters

**公式ドキュメントを参照していますが、私の解釈が誤っている場合もあるため間違っていた場合はご指摘ください。**
記事作成時点のfluentdの最新バージョンは1.2.2です。

主にbufferに関するパラメータは上記の三種類となります。
retryに関しては下記のページでも紹介しているので特にここでは記載しません。
参考：
https://qiita.com/smith_30/items/1a8df503613f7e7e2904
https://qiita.com/tatsu-yam/items/bd7006e483f3b3c64309

また、buffer/chunk/flush/queue等の動作に関してもある程度上記で説明してくださっているので参考にしてみると良いと思います。（ちょっと古いけど）
bufferファイルの作成単位に関しては、tag/timekey等のmeta情報の知識も必要ですが、ここでは書きません。（気が向いたら追記します。）

##buffering parameters
ここでは、主にbufferのファイルサイズや分割に関する設定を説明します。
bufferのサイズは、主に転送（書き込み）等のflunetdから外部へ送信される際のデータの出力単位だと思ってもらって良いと思います。

ここの設定により、送信先のデータ受信の最大サイズにあったチューニングや、ディスク書き込みの際のブロックサイズに合わせて設定を行うことができます。
まれに処理レコード数の制限が存在する出力先が存在した場合などは送信単位を50レコードまでと設定する必要があったり、、

（ただ厳密にここの設定が守られているわけではなく、一定周期でwatchしており設定値を超えたら次のファイルを作成するなどの動作のため設定値を超える場合もある。）

###chunk_limit_size
ここでは、作成されるbufferファイルの最大サイズを設定可能。
この設定値か、*chunk_limit_size*の設定でファイルが分割される。

入力データの大きさによりここで設定したファイルサイズを超える入力があった場合エラーが頻出しますので、その際はここのパラメータを上げるか、入力元を絞る必要があります。
**厳密にはflushの設定も関係するがここでは割愛します。**


###chunk_limit_records
一つのbufferファイル内の最大レコード数を設定可能。
ここで設定したレコード数を超えると新しくbufferファイルが作成される。

####total_limit_size
bufferプラグイン内で溜め込める合計bufferサイズ。
outputプラグインで何らかの原因で出力が出来ない状態で、flunetd側のbufferで溜め込めるbufferのサイズとなる。
このサイズは、flunetd全体に適用されるのではなく、bufferプラグインごとに設定されるためディスクサイズやメモリサイズに考慮して設定する必要がある。

**例えば、ディスクサイズが128GBなのにbuffer_fileプラグインを2つデフォルトで利用していると最大で128GB貯まるため、ディスクフルとなる可能性がある。**

###chunk_full_threadhold
bufferファイルをflushする際のファイルサイズに関連する項目。
上記では、*chunk_limit_size*を超えるとbufferファイルが新しく作成されると、書いたが厳密には*chunk_limit_size* × *chunk_full_threadhold* のサイズを超えるとflushされ、新しいbufferファイルが作成される。


##flushing parameters
ここではfluentdのflushの際の動作に関するパラメータを設定する。
簡単にflushの動作を説明すると
bufferの状態としては、*staged*/*enqueued*の状態が存在し、*staged*の状態から*enqueued*の状態へ移行する処理がflushである。（ここちょっと自信ない）

####flush_at_shutdonw
fluentdを終了する際に保持しているbufferファイルをすべてflushする設定。
buffer_memoryを利用している場合、この設定を行わないとメモリ内のbufferが損失するため、設定を行うことをおすすめします。

また、buffer_fileを使用している場合はbufferの損失は起きませんが扱うデータ量が多い(または大量のbufferファイルが作成される環境）場合は次回起動時にbufferの読み込み処理に時間がかかるため、これを避けたい場合は設定を有効にすることをおすすめします。

####flush_mode
ここはflushの判定ロジックを設定可能

- lazy

timekey毎にflush/writeを行う。特にリアルタイム処理が不要であったりする場合はデフォルトでこの設定なので変えなくても良いと思う。

- interval

後述する*flush_interval*の設定値ごとに一定間隔でflushを行う。

- immediate

bufferが作成されたらすぐにflushを行う。
データ入力が極端に大きい場合は、この設定で良いと思うが小さなデータが細々と入力される環境だとプロセスのCPU使用率が上がるためこの設定は避けること。
処理データのサイズを小さくしたい場合はこの設定が有用。

####flush_interval
前述の*flush_mode*で*intervalを指定した際に設定可能

####flush_thread_count
enqueueされたデータをoutputプラグインにより処理するthread数を設定する。
基本的にこの設定を上げると、outputプラグインの処理速度が上がるがCPU使用率が上がるため気をつけること。
公式ドキュメントではボトルネックがディスクにある場合は、この設定で書き込みを平行に行うことである程度ディスク書き込み遅延による性能劣化を避けることが可能だと記載されている。

####flush_thread_interval
enqueuedされたデータが存在しない場合の、データ入力監視の感覚（ざっくり）
この数値を小さくすると、enqueueされたデータが新規にできた際のoutputまでの処理のタイムラグが小さくなるが、入力データが存在しない場合のCPU使用率が上がるため基本的には0.1以上に設定することをおすすめする。
**0.01に設定したときは入力データが存在しないのに常時CPU30%ほど使用していた。
  0.1に設定すると5%以下に収まった。。**

####flush_thread_burst_interval
*flush_thread_interval*と異なり、すでにenqueueされているデータが存在する場合のoutputでの処理感覚（ざっくり）
この数値を小さくするとoutputプラグインでの処理間隔が短くなり処理速度が上がるが、CPU使用率が上がる。

####overflow_action
*otal_limit_size*の設定等で上限値に到達した場合、fluentdは追加収集されるデータの処理を以下の三つの対処が可能。

- throw_exception

追加でデータが入力されるごとにexceptionが発生する。
exceptionの発生契機はrecordの入力単位で発生するようなので、1sごとに100record入力があると100回exceptionが発生する。
fluentd自身のログも収集していたりするとexceptionの無限ループになるので気を付けること

- block

追加のrecordの入力を文字通りblockする。
追加入力されたrecordはfluentdで処理されることはなく、古いbufferが保持されたままになる。

bufferが処理されて猶予が生まれた場合、in_tailプラグイン等は最後に読み込んだpositionから読み込みを再開する。（該当ファイルが存在した場合）
in_forwardなどでリトライオーバーとなっていた場合は、データの欠損が発生する。

また、blockとした場合停止するのはすべてのin_pluginの動作であるので、bufferの設定を分割していた場合でも影響があるので注意すること

例：Aのbufferでは、保持可能なbufferに余裕があるが、Bのbufferで上限値に達してかつoverflow_actionをblockにしていた場合、Bでも追加の処理は行われなくなる。

- drop_oldest_chunk

文字通り、古いchunkを破棄して新しいchunkを読み込む。
古いデータは順番に破棄されていく。

新しいデータを優先に保持したい場合はこの設定を利用する。
古いデータを保持したい場合は、*throw_exception* or *block* を使用すること

#まとめ
flunetdのbuffer周りの設定は下手すると処理速度に直結するため大容量のデータを扱う際は慎重に設定することをおすすめします。
あとは、出力先への負荷の削減等。

参考：https://docs.fluentd.org/v1.0/articles/buffer-section#buffering-parameters