ぬけラボ

φ(..)メモメモ

fluent-plugin-http-ex をリリースしました!

Fluentd in_http プラグインにデータを送る際、ある程度データをまとめて送ったり、in_forward のように高速に処理させたかったので in_http にいくつか機能を追加した in_http_ex をリリースしました!!

  • github

https://github.com/hiro-su/fluent-plugin-http-ex

  • rubugems

https://rubygems.org/gems/fluent-plugin-http-ex

in_httpからの変更点

1. 受信フォーマットに list と chunked の追加

受信フォーマットに list と chunked を追加。

  • JSON list の場合
'[{"action":"login","user":2},{"action":"login","user":2}]'
  • MessagePack list の場合
record = {"action" => "login", "user" => 2}
[record,record].to_msgpack
  • chunked の場合

HTTP1.1の Transfer-Encoding: chunked でデータを受取ります。chunkedはMessagePack形式の物だけを想定しています。以下、リクエストヘッダ部分だけを抜粋。

POST /ms/test.tag HTTP/1.1
Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: */*
User-Agent: Ruby
Content-Type: application/x-msgpack
Transfer-Encoding: chunked
Connection: Keep-Alive
Host: localhost:8888
2. content-typeの追加

Content-Type ヘッダフィールドに application/x-msgpack を追加しました。msgpack形式時は application/x-www-form-urlencoded よりBodyにパラメータを付けない分、速度面で多少有利な気がします。

3. tagの前にresourceを追加

resourceにより受けるフォーマットを分離。

  • resource無し

in_httpと同じ形式です。

http://localhost:8888/tag.here
  • json

jが1レコードのjsonでjsがlistを受けます。

http://localhost:8888/j/tag.here
http://localhost:8888/js/tag.here
  • msgpack

mが1レコードのMessagePackでmsがlist, chunkedを受けます。

http://localhost:8888/m/tag.here
http://localhost:8888/ms/tag.here
4. keepalive_timeout

keepalive_timeout 0sでコネクションが切れないように変更

簡単な使い方

例えば、JSON list形式

$ curl -X POST -H 'Content-Type: application/json' -d '[{"action":"login","user":2},{"action":"login","user":2}]' \
    http://localhost:8888/js/test.tag.here;

Fluentd側では以下のように受信します。

2013-08-07 19:42:22 +0900 test.tag.here: {"action":"login","user":2}
2013-08-07 19:42:22 +0900 test.tag.here: {"action":"login","user":2}

パフォーマンス

簡単にですが、それぞれのフォーマットの速度比較をしてみました。
in_http と in_http_ex に対して 10,000 record を送ります。
使用したコードはexamples以下に起きました。
https://github.com/hiro-su/fluent-plugin-http-ex/tree/master/examples

  • マシンスペック
Mac OS X 10.8.2
1.8 GHz Intel Core i5
8 GB 1600 MHz DDR3
コンフィグ
<source>
  type http
  port 7777
  bind 0.0.0.0
</source>

<source>
  type http_ex
  port 8888
  bind 0.0.0.0
  body_size_limit 300M
  keepalive_timeout 0s
</source>

<match **>
  type stdout
</match>
結果

in_http: json

$ time ruby examples/json.rb

real    2m27.480s
user    0m7.252s
sys     0m4.438s

in_http: msgpack

$ time ruby examples/msgpack.rb

real    2m36.408s
user    0m8.249s
sys     0m4.441s

in_http_ex: json

$ time ruby examples/json.rb

real    2m30.639s
user    0m7.195s
sys     0m4.686s

in_http_ex: msgpack

$ time ruby examples/msgpack.rb

real    2m28.442s
user    0m7.126s
sys     0m4.324s

in_http_ex: json list

$ time ruby examples/json_list.rb

real    0m18.179s
user    0m0.872s
sys     0m0.477s

in_http_ex: msgpack list

$ time ruby examples/msgpack_list.rb

real    0m13.787s
user    0m0.908s
sys     0m0.470s

in_http_ex: chunked

$ time ruby examples/nc_chunked.rb

real    0m1.584s
user    0m0.244s
sys     0m0.107s

さいごに

簡単なパフォーマンス測定でしたが、 json < msgpack < json list < mgpack list < msgpack chunked のような結果になりました。msgpackのchunked形式がやはり速かったです。バッチ処理的に1日分のファイル内容をFluentdに対して送信したりする時に良さそうです。

ただ、個人的に一番取り扱いが良さそうなのは、json listとmsgpack listだと思っています。
また、バグや改善点など有りましたらどんどん pull req して頂ければと思います!