タグによってforward先を一意にしつつ負荷分散したい時に使えるかもしれないfluent-plugin-hash-forward #fluentd
そろそろ fluentd 触ろうかと思ってはや 1 年近くが経とうとしている今日この頃。ふと構成を色々考えてたんですが、ひとつ気になる問題がありました。
forward とか roundrobin とかでログの転送先をいろんなサーバにすることがあると思うのですが、単純な count up 以外の集約を行おうとすると、サーバ(正確には flunetd のインスタンス)が別れてるとちょっと面倒ですよね。例えば、アクセスログから 1 分辺りのステータスコードによって datacounter するとして、それを出力してるサーバ毎にやりたいと思った時に、一つのサーバからの出力がラウンドロビンされていろんな fluentd に分かれていると、ちょっと厳しい。
また、例えば 1 サーバで in_forward の受け口は 1 つにしつつ、ローカルに別プロセスでいくつも fluentd を上げてそれらにロードバランスしようかと思った時にも、単純にラウンドロビンしちゃうと、せっかく 1 サーバに集めたのに処理がプロセスで別れてしまって悲しい。
なにができればいいのかなぁと考えると、例えばアクセスログの処理用の worker サーバをいくつか横に並べた時に、「accesslog.server1」とタグがあったら、worker1 に、「accesslog.server2」とタグがあったら worker2 に、みたいな感じでタグによって一意に決まると嬉しそう。
ただ、こんな単純なルールだとタグの種類だけ worker を準備しないといけないわけで、もうちょっと賢くやりたい。というわけで、タグを murmurhash で int に変換して、それを worker の数で剰余を取ってバランスするといいかなと思って、fluent-plugin-hash-forward というプラグインを試しに書いてみました。
仕組みとしては tagomoris さんの fluent-plugin-forest を大いに参考にさせて頂いています(というかコピペしてます><)。config で指定したサーバの数だけ out_forward(server は 1 つのみ)のインスタンスを作成して、emit の中で tag を murmurhash してどのサーバに振るかを一意に決めています。
config は以下の様な感じで、見てもらえばわかる通り out_forward っぽいです。<server>
の部分と add/remove_prefix 以外は実際内部的に生成する out_forward にそのまま渡されます。
<match pattern>
type hash_forward
add_prefix hoge
flush_interval 1s
<server>
host 192.168.1.3
port 24224
</server>
<server>
host 192.168.1.4
port 24224
</server>
<secondary>
type file
path /var/log/fluent/forward-failed
</secondary>
</match>
こんな感じで server を並べて書いてあげると tag の文字列によって良い感じに負荷分散してくれると思います。使いどころがあるのかどうかは定かではないですが、興味ある方がいればインプット頂ければと思います!