fluent-logger について

こんにちは。Fluentd Advent Calendar 11日目担当の @komamitsu です。ワイワイ。

Fluentd Advent Calendarにノリで登録したもののfluentd本体やプラグインに余り関わっていないので途方に暮れていましたが、fluent/fluent-logger-java のメンテナンスをしていることもあり、fluent-logger周りのことを書いてやりすごしたいと思います。

fluent-logger-javaの一年

地味な見出しですね。自分でも書いてみて素でちょっと引きましたが、とりあえずfluent-logger-javaに関連した出来事などを...

いくつか細かいバグの修正や改善を入れていますが、その中でもTCP切断後の再接続処理やタイムアウトの問題が改善されているので、地味に使いやすくなっていると思います。

MLより。複数のfluentdに対して障害時のfailover、またはメモリバッファが一杯になったらファイル書き出し出来ないの?fluentdのメンテ中にメモリバッファがあふれちゃうよ的な話。確かに一理ある要望(まだ対応できてませんが...)

実のところ、TDでは全てのサーバーにfluentdがいて、アプリからは自サーバーのfluentdに投げているのであまり接続周りで困ったことがないんですよね... なので違う構成で利用されている方で困っているケースがあれば色々と知りたいなぁと思ってる次第です。

あとJavaのlog frameworkとの連携に関する要望とかもたまに目にしますねぇ。需要がどの程度あるのか気になります。

他のfluent-loggerとの比較

fluent-logger-javaは万一送信先のfluentdに送信出来なくてもメモリ上でバッファリングを行い、次回以降の送信成功時にまとめて送るようになっています。しかし、前述の "じゃあメモリバッファに書ききれなくなったらどうするの?ディスクに書き出すの?fluentdの接続先を変えてくれるの?" という要望には答えきれてないように思いました。そこで、他のfluent-loggerはどんな感じなのか気になったのでざっとコードを眺めてみました。

切断後の再接続の有無 再接続がexponential backoff? 送信失敗時のデータ保持 socket domain
Java fluent/fluent-logger-java yes yes yes INET
Ruby fluent/fluent-logger-ruby yes yes yes INET
Python fluent/fluent-logger-python yes no yes INET,UNIX
Perl fluent/fluent-logger-perl yes yes yes INET,UNIX
PHP fluent/fluent-logger-php yes yes no INET,UNIX
Node.js fluent/fluent-logger-node yes no yes INET
D fluent/fluent-logger-d yes yes yes INET
Scala oza/fluent-logger-scala yes yes yes INET
Haskell notogawa/fluent-logger-haskell yes no yes INET
OCaml fluent/fluent-logger-ocaml yes yes yes INET,UNIX
C roadman/fluent-logger-c no - no INET
C++ todayman/fluent-logger-cpp no - yes INET
C# zoetrope/fluent-logger-csharp yes no yes INET
Lua ngigroup-developer/fluent-logger-lua no - no INET

# Haskellもあったけど眠気の限界。気力があったら後で追加します...notogawaさんから教えて頂きHaskell版追記しました。thanks!

# 全体的にざっと眺めただけ&上記全ての言語についてちゃんと理解しているかというとそうではないので、間違っていたらご指摘頂けると幸いです。

全てのfluent-loggerでfluentdとの接続を保持しており、毎回接続しなおさないようになっていますが、それ以外は結構違いがあって面白いです。fluent-loggerのほうでどこまで頑張るか、呼び元のほうで頑張るかなど思想の違いもありそうです。(2013-12-11 思い出したので追記 ->) それ以外にも、Perl版ではfork()されたプロセスではsocketを共有せずに自分で開き直すような処理があったりして、そういう渋い工夫を見るのも楽しいですね。

ちなみに、複数のfluentdに接続してfailoverしたり、メモリバッファが溢れたらディスクに書き込む機能はどれもありませんでした。意外とそれで困るケースはすくないのかな。

一点気になったのが、いくつかのfluent-loggerではsocketへの書き込みのみを続けているっぽいので、fluentdが万一落ちたときにFINパケットが飛んで来ても気がつかないケースがありそうかなと。select()的なことをしてread()して0byteであったら切断を検知, またはnon-blockingでread()してEAGAINを期待する、ということが必要な気がしました。fluent-logger-rubyだと毎回別socketで接続しているようで、これであればFINを送る間もなく切断した場合でも検知出来るなー、でもちょっとコストが心配だなーと色々面白いです。

あと、自分では計測していないのですが、UNIX domainソケットのほうが性能が出るっぽい話も聞くので、優位な差がありそうであればJava版も対応してみても良いかな、などなど。

fluent-logger-ocaml

前述のfluent-logger軍団を見ていたらOCaml版が無いことに気がついたので、枠を埋める意味合いで作ってみました。

komamitsu/fluent-logger-ocaml

再接続の間隔をよろしくやってくれる機能はまだ付けてない(送信の度に毎回再接続を試みてしまう)のですが、それ以外はそれっぽく動くような気がします。あとテストが無くて意識の低さを露呈した感じになっています。MessagePackのシリアライズには mzp さんの msgpack/msgpack-ocaml を使わせて頂きました。型!


明日は katzchang さんです。