fluent-plugin-kinesis Ver2 の圧縮オプションがすごい話
Amazon Kinesisへデータを送る方法として、Fluentdを使用するのはよくあることかと思います。
その際使用するプラグインはaws-fluent-plugin-kinesisでしょう。
このプラグイン、とてもいいんですが、
問題があるとすると、ログレコードの圧縮が難しい ことです。
ログレコードを圧縮することが出来れば
- 1シャードあたりの1MB/sec 制限内でより多くのレコードを処理できる
- シャード数を減らせる
- Lambdaをトリガーしている場合、Lambda実行回数が減らせる
というメリットがあります。
かつては zlib_compression
というオプションがあったようですが、いつの間にか非推奨になっていたようです。
ところが最近「Version 2.0」がリリースされ「compression」オプションが新たに追加されていました!!
さっそく試してみます。
前提
KPLの使用
1レコードにログレコードを圧縮させる技術である「KPL」を使用します。
fluent-plugin-kinesisでは「kinesis_streams_aggregated」を使用すると実現できます。
ちなみに「kinesis_streams_aggregated」は、Ver1系では「kinesis_producer」という名前でした。
システム構成
システム構成は以下のようにしてます。
それぞれ1台(1個)ずつ存在しています。
[Fluentd on EC2] => [Kinesis] ⇒ [Lambda] ⇒ [S3]
fluent-plugin-kinesisからKinesisへログを送信します。
KinesisはそのイベントをトリガーとしてLambdaにデータを渡し、LambdaはS3にログを出力します。
Kinesisへログが吐かれるたびに、S3にファイルが出来るイメージです。
検証方法
11KB程度のログを1秒間に100回ログに出力し、Kinesisに出力します。
以下詳細です。
検証方法 詳細
どのくらいログサイズが圧縮されているかを見るために、でかいJSONファイルを用意します。
今回は以下のようなものを用意しました。
Name | Size |
---|---|
sample.json | 11KB |
中身はでかいのでここには載せませんが、よくある設定ファイルのようなフォーマットです。
このJSONを以下のスクリプトを使用し、ログファイルに出力します。
$ vim test.sh #!/bin/bash start=$(date) for i in $(seq 1 ${1}) do echo ${i} echo -en "number:${i}\tjson:$( echo $(cat sample.json))" >> /var/log/test.log sleep 0.01s done echo ${start} date
だいぶ雑なシェルですが、引数で渡された数値分、JSONを「/var/log/test.log」に出力します。
1秒間に100回ログを出力します。
このログをKinesisに送信します。
Fluentdの設定
Fluentdの設定はこんな感じです。
$ source.conf <source> @label @aggregate @type tail format none tag "test.log" path /var/log/test.log pos_file /var/tmp/test.log.pos read_from_head true </source> $ match.conf <label @aggregate> <match **> @type kinesis_streams_aggregated region ap-northeast-1 stream_name ${stream_name} include_tag_key true flush_interval 60s buffer_chunk_limit 1m buffer_type file buffer_path /var/tmp/buffer/kinesis compression zlib </match> </label>
以下の条件のどちらかを満たす場合、FluentdはKinesisにデータを送信します。
- ログバッファサイズが1MBを超える
- 1分が経過する
Lambdaの設定
Lambdaでやることは以下のとおりです。
- KPLで圧縮されたレコードを紐解く
- データ自体はgzipで圧縮されているためそれの解凍
- 受け取ったデータをS3に出力
検証
compressionオプションを無効にした状態と有効にした状態で実行し、比較します。
# ログ出力を1万回実行 ./test.sh 10000
結果がこちら
compressionの有無 | 出力ファイル数 | 出力ファイルの平均サイズ |
---|---|---|
無効 | 62 | 約1.3MB |
有効 | 12 | 約7.0MB |
compressionオプションを有効にすると、これだけの差が出ました。
Kinesisの1シャードは、「1秒間に1MBのデータしか受け付けない」という制限がありますが
1回のログ送信で約7MB分のログデータを送れたことになるので、かなりインパクトがでかいです。
上記検証では、1レコードサイズにしては巨大なサイズにしてしまったので、
よくある感じのログレコードを大量に出力させたいと思います。
# sample log 127.0.0.1 - - [02/Jan/2017:23:46:58 +0900] "GET /favicon.ico HTTP/1.1" 200 318 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0" "-"
# ログ出力を1万回実行 ./test.sh 10000
結果がこちら
compressionの有無 | 出力ファイル数 | 出力ファイルの平均サイズ |
---|---|---|
無効 | 3 | 約540KB |
有効 | 3 | 約540KB |
Fluentdのbuffer_chunk_limitを1MBにしている影響で、
1分(flush_interval)が経過しログが送信されたので違いがなくなっています。
buffer_chunk_limitを100KBにしてみます。
compressionの有無 | 出力ファイル数 | 出力ファイルの平均サイズ |
---|---|---|
無効 | 25 | 約64KB |
有効 | 23 | 約70KB |
若干ではありますが、compressionオプションを有効にしたほうがファイル数は少なく済みました。
検証結果
最後に
今回はKPLを使用しましたが、通常のKinesis Streamの場合は
1レコードずつ圧縮して送信されるため、通信経路上もサイズ削減の恩恵を受けることが出来ると思います。
可能ならば、fluent-plugin-kinesisのVersionを2にあげて圧縮を有効にしたほうがいいかもしれません。
では!