Raspberry PiでFluentdを立ち上げてTDにデータを流してみた話

一ヶ月程前に同僚である @doryokujin 先生からRaspberry Pi(面倒なので以下Pi)を頂いたのだけど、Piに必要なSDカードが手元に無くてすっかり放置していたのですが、満を持してSDカードを買ってきたのでちょっとPiを立ち上げてみた。という話を備忘録的に。
 
必要なもの(というかこれで間に合った、的なもの)

  • USBケーブル
  • RCAケーブル
  • USBキーボード
  • LANケーブル
  • SDカード(SDHD 8GB)

 
startxとか叩かなければUSBマウスは要らない。
 

Piの立ち上げ

  • 準備に使った環境はMac OX 10.8.5
  • SDカードは挿してある状態
  • SDカードの/dev/disk番号を確認してunmount
$ diskutil list
/dev/disk0
     :
/dev/disk4
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.8 GB     disk4
   1:                 DOS_FAT_32 NO NAME                 7.8 GB     disk4s1
$ diskutil unmountDisk /dev/disk4
Unmount of all volumes on disk4 was successful

 

  • OSにはRaspbianを選択。2014-01-07-wheezy-raspbian.zip を落としてきて展開したimgファイルをddで書き込み。かなり時間がかかる
$ sudo dd bs=1m if=~/Downloads/2014-01-07-wheezy-raspbian.img of=/dev/disk4
Password:
2825+0 records in
2825+0 records out
2962227200 bytes transferred in 1071.833726 secs (2763700 bytes/sec)
  • ddでイメージが書き込まれたSDカードをPiに挿してMBPとか適当なやつからUSBケーブルをつなげて電源を供給して上げれば起動
  • 自宅にディスプレイが無いので、あまり使われていないアナログテレビを用いて動作確認。RCAケーブルの黄色いやつ(映像用)をつなげれば滲んだ雰囲気の画面で確認出来る
  • Setting画面が表示されてユーザーのパスワードの変更とか色々できるので、やりたい場合はやる感じで。SSHの設定に関しては失敗してたけどひとまず先に進む
  • Settingを終えるとlogin promptが表示されるのでlogin。sshdも起動していたのでログインしてみたら普通に入れた。
  • Rubyは1.9.3, Javaは1.7が入っていて良い感じ

 

Fluentdとかを入れてTDにデータを流し込んでみる

  • Fluentdの安定版であるtd-agent(http://docs.fluentd.org/articles/install-by-deb)入れようかと思ったけど、何となくgemから入れてみた。FluentdはC拡張のビルドが発生するので、ruby-dev的なものを入れておく
$ sudo aptitude install ruby-dev
$ sudo gem install fluentd
  • TreasureDataにデータを入れるのでfluent-flugin-tdも。というか事前にTDのアカウントが必要なので適当に作っておくのが前提
$ sudo fluent-gem install fluent-plugin-td
  • fluentdのconfファイルを作成(/home/pi/fluentd/fluent.confとか)。入力はin_forwardだけの超シンプルな設定。出力はout_td。
<match td.*.*>
  type tdlog
  apikey <replace this with your TD API key!>
 
  auto_create_table
  buffer_type file
  buffer_path /home/pi/fluentd/td
</match>
 
<source>
  type forward
</source>
  • fluentd起動
$ fluentd -c /home/pi/fluentd/fluent.conf

fluentdデーモンとして起動したい場合は以下のようにしても良いかも。

$ export FLUENTD_ROOT=/home/pi/fluentd
$ fluentd -c $FLUENTD_ROOT/fluent.conf --log $FLUENTD_ROOT/fluentd.log --daemon $FLUENTD_ROOT/fluentd.pid
  • fluent-catとかfluent-postコマンドなどでレコードを放り込んでみる
$ echo '{"name":"pi", "age":49}' | fluent-cat td.pidb.test
  • td tablesコマンドで件数を確認
$ td tables pidb
+----------+-------+------+-------+--------+---------------------------+---------------------------+-----------------------+
| Database | Table | Type | Count | Size   | Last import               | Last log timestamp        | Schema                |
+----------+-------+------+-------+--------+---------------------------+---------------------------+-----------------------+
| pidb     | test  | log  | 1     | 0.0 GB | 2014-02-15 23:17:20 +0900 | 2014-02-15 23:14:15 +0900 | age:long, name:string |
+----------+-------+------+-------+--------+---------------------------+---------------------------+-----------------------+
1 row in set
  • td query コマンドでクエリーを投げてみる
$ td query -w -d pidb 'select name, age from test'
   :
Status     : success
Result     :
+------+-----+
| name | age |
+------+-----+
| pi   | 49  |
+------+-----+
1 row in set

 
見返してみると、記事にするほどの内容でも無い気がしてきたけど、勢いで書いたのでまぁ良いのではと。
 
PiにはGPIOとか付いているのでセンサー的なものをくっつけて、そこからの情報をTDに送り続けるというのは割と簡単に出来そう。データ量をあまり気にせずどんどん放り込んで後で集計の切り口を試行錯誤しやすいのは、1TDユーザーとしても使っていてかなり楽なので相性が良さげ。

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 さんです。