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
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のマルチスレッド処理を使うことになりました。