case-kの備忘録

日々の備忘録です。データ分析とか基盤系に興味あります。

jRubyを使いfluentdのマルチスレッド処理を高速化できるか検証してみた

rubyでマルチスレッド処理を使うとGILの制約により、CPUのコアをうまく使えなかったのでGILの制約を受けないjRubyで実行する方法を試してみました。マルチプロセスだとinput pluginからout put pluginに渡すrouter.emit_streamがうまく機能しなかったためです。fluentdをjRubyで実行したかったのですが、検証したかぎりでは難しそうでした。役立つ場合もあるかと思うので備忘録として残せrばと思います。

Parallel.map(list, in_threads: @parallel_in_threads) do |rows| puts rows end

https://stackoverflow.com/questions/29215989/collecting-results-for-ruby-parallel-gem

# use jruby to use multi core to avoid GIL for `router.emit_stream` method
# https://github.com/puckel/docker-airflow/issues/182#issuecomment-444683455
# https://www.jruby.org/download
mkdir -p /usr/share/man/man1
apt-get install openjdk-8-jre -y
wget https://repo1.maven.org/maven2/org/jruby/jruby-dist/9.2.17.0/jruby-dist-9.2.17.0-bin.tar.gz
tar zxf jruby-dist-9.2.17.0-bin.tar.gz
mv jruby-9.2.17.0 /usr/local/jruby
/usr/local/jruby/bin/jruby -v

# ref
# jruby: https://stackoverflow.com/questions/29215989/collecting-results-for-ruby-parallel-gem
# je: https://github.com/kzk/jemalloc-rb#usage
/usr/local/jruby/bin/jruby -S je fluentd -c /usr/src/app/config/fluent-local.conf -p /usr/src/app/fluent-plugin-sql-server/lib/fluent/plugin


Jrubyでfluentdを実行しましたが、プロセスを確認したところjRubyで実行できておらず通常のrubyでした。
rbenvを使い、rubyコマンドでjrubyを実行できるよう修正したところ、fluentdで必要とされるライブラリの対応ができてませんでした。

 apt-get install rbenv

apt-get install -y git
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

rbenv install jruby-9.2.17.0
rbenv local jruby-9.2.17.0

echo eval "$(rbenv init -)" >> ~/.bashrc
source ~/.bashrc
ruby --version

対応してるライブラリもあれば対応してないライブラリもある。

ruby -S gem install json -> ok
ruby -S gem install tiny_tds -> no

stackoverflow.com

fluentdでがJrubyはまだサポートされていないようです。
github.com

今回fluentdでSQL Serverの取得結果をPub/Subに書き出したかったのですが、input pluginからfilter, output pluginに渡すためにrouter.streamを使う必要があります。
マルチプロセスではグローバル変数にしても参照はできても、メモリが共有されないため書き込みはできません。
router.streamはうまく動かないことがわかりました。deepコピーなども試しましたが、サポートされていないクラスでした
router.emit_stream: https://github.com/fluent/fluentd/blob/master/lib/fluent/event_router.rb#L114


最終的にはI/Oが起きる形でRubyのマルチスレッド処理を使うことになりました。