はじめに
ストリーム処理の需要の高まりから、最近注目されている時系列 DB InfluxDB ですが、Fluentd 経由で InfluxDB へデータを転送する際、落とし穴があったので紹介します。
(追記 2016-06-07) この問題は、 https://github.com/influxdata/influxdb-ruby/pull/121#issuecomment-208588626 にて解決しました。
fluent-plugin-influxdb にある落とし穴
Fluentd を通して InfluxDB へデータを転送する際に、利用可能なプラグインに fluent-plugin-influxdb があります。このプラグインの実装は InfluxDB の Ruby クライアント influxdb-ruby のインスタンスを生成し、インスタンスの write_points
メソッドを使用して InfluxDB にデータを転送するという非常にシンプルなものです。
しかし、fluent-plugin-influxdb には、influxdb-ruby のインスタンスがエラーで落ちると、それ以降 InfluxDB にデータ転送できなくなるという落とし穴があります。データが転送できなくなっても Fluentd のプロセスは動き続けるので、その点も注意が必要です。プロセスが動き続けているから問題ないと思っていると、いつの間にかデータが可視化できなくなっていたり、バッファファイルが肥大化したりしてしまっています。
2015-10-21 17:21:33 +0900 [warn]: temporarily failed to flush the buffer. next_retry=2015-10-21 17:23:43 +0900 error_class="InfluxDB::Error" error="unable to parse 'test,status= count=2 1445414291': missing tag value\n" plugin_id="object:1ebf6a8"
influxdb-ruby のインスタンスは Fluentd プロセスを再起動すれば復活するのですが、未だ問題があります。現在、influxdb-ruby にはデータのエスケープに幾つかの不具合があり、エスケープが必要なデータを転送してしまうと問題が再発してしまうのです。このため、たとえ Fluentd プロセスを再起動しても、Fluentd のバッファファイルにエスケープすべき、もしくは空値のデータが含まれていると問題が解消しません。
対策
現在、私を含め influxdb-ruby を修正した PR (TrickyMonkey の PR, yhara さんの PR) が投げられているので、その元のブランチのコードを使うと一先ず解決できます。自分で言うのもなんですが、yhara さんのブランチがいいと思います。influxdb-ruby は、元の実装上、InfluxDB の仕様に則ったエスケープをすることが難しく、私の PR は「仕様とは違っているが、問題を解決できる最小限の変更」になっており、yhara さんの PR は「仕様に準拠しているが、やや大きな変更」になっています。私の利用範囲では、私の PR で問題無いですが、安全なのは仕様に準拠している方ではないかと思っています。
このため上記の PR がマージされれば、多くの問題は解決すると思っています。ただ、yhara さんの大きめのパッチが直ぐにマージされるかが分からないので、今回あえて記事にしました。
まとめ
この記事を見ると、Fluentd と InfluxDB の相性は悪いのではないかと誤解させてしまうかもしれませんが、Fluentd と InfluxDB の組み合わせは非常に強力です。両ミドルウェアともに、非常に簡単にデプロイでき、スケールアウトさせることもできます。ストリーム処理をスモールスタートからはじめるには、これらのミドルウェアは悪くない印象を持っています。
この記事は、あくまで、現在そして近い未来に、Fluentd と InfluxDB の利用を検討されている方の躓きを未然にふせぐためのものです。この記事で、ストリーム処理を楽しく気軽に運用できる人が増えればいいなと思っています。(この記事を書いたのに、次の日には問題が解決していたというオチを期待しつつ…)