こんにちは! ツカノ(@snuffkin)です。
ElasticsearchとKibanaを使うとログなどを簡単に可視化できるため、利用者が急速に増えてきています(私もそのひとりです)。様々なブログで紹介されているKibana画面はとても素敵で、積極的に使いたくなります。
ただ、それなりの規模でElasticsearchを利用するには、中身を知ったり、データ設計や運用面なども考える必要がありますが、そのあたりの情報はまだ十分ではないように思います。そこで、Elasticsearchの中身をもっと知るために、ひとりでひっそりソースコードリーディングをしてみました。
今回利用したElasticsearchのバージョンは1.0.0.RC2です。以下の場所から実行媒体とソースコードをダウンロードして確認しています。また、確認はWindowsで行っています。
- 実行媒体 http://www.elasticsearch.org/downloads/1-0-0-RC2
- ソースコード https://github.com/elasticsearch/elasticsearch/tree/v1.0.0.RC2
1.ElasticsearchはどんなJVM引数で起動するのか?
まずは、実行媒体(zip)を展開します。ひとまずデフォルト設定のままで、elasticsearch.batを実行して起動します。
以下のようなログがコンソールに表示されて、起動完了です。
[2014-02-07 06:35:10,225][INFO ][node ] [Blind Faith] version[1.0.0.RC2], pid[9052], build[a9d736e/2014-02-03T15:02:11Z] [2014-02-07 06:35:10,225][INFO ][node ] [Blind Faith] initializing ... [2014-02-07 06:35:10,229][INFO ][plugins ] [Blind Faith] loaded [], sites [] [2014-02-07 06:35:13,525][INFO ][node ] [Blind Faith] initialized [2014-02-07 06:35:13,526][INFO ][node ] [Blind Faith] starting ... [2014-02-07 06:35:13,743][INFO ][transport ] [Blind Faith] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/172.20.10.4:9300]} [2014-02-07 06:35:16,971][INFO ][cluster.service ] [Blind Faith] new_master [Blind Faith][NYDlh_0TRJeafDu2KZxB1A][Poincare][inet[/172.20.10.4:9300]], reason: zen-disco-join (elected_as_master) [2014-02-07 06:35:17,007][INFO ][discovery ] [Blind Faith] elasticsearch/NYDlh_0TRJeafDu2KZxB1A [2014-02-07 06:35:17,039][INFO ][gateway ] [Blind Faith] recovered [0] indices into cluster_state [2014-02-07 06:35:17,140][INFO ][http ] [Blind Faith] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/172.20.10.4:9200]} [2014-02-07 06:35:17,141][INFO ][node ] [Blind Faith] started
さて、VisualVMを起動して、Elasticsearchに接続してみましょう。以下の図の赤枠で囲った部分にElasticsearchが見えていますね。
「概要」タブをクリックして、JVM引数を確認してみると、以下のようになっています。
(es.path.homeは実行媒体を展開したディレクトリによって異なります)
-Xms256m -Xmx1g -Xss256k -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -Delasticsearch -Des-foreground=yes -Des.path.home=C:\elasticsearch-1.0.0.RC2
これら設定値はelasticsearch.batの中に記載されているため、JVM引数を変更する場合はこのファイルを修正してください。Linux版の場合はelasticsearch、elasticsearch.in.shにまたがってJVM引数の設定が記載されています。
2.Elasticsearchのスレッド構成は?
引き続き、VisualVMを操作します。「スレッド」タブから「スレッドダンプ」ボタンを押して、スレッドダンプを取得してみましょう。ちょっと長いですが、取得したスレッド一覧は以下の通りになりました。(見やすいように並び替えています)
Attach Listener C2 CompilerThread0 C2 CompilerThread1 Concurrent Mark-Sweep GC Thread DestroyJavaVM elasticsearch[Blind Faith][[timer]] elasticsearch[Blind Faith][[ttl_expire]] elasticsearch[Blind Faith][clusterService#updateTask][T#1] elasticsearch[Blind Faith][discovery#multicast#receiver][T#1] elasticsearch[Blind Faith][generic][T#1] elasticsearch[Blind Faith][http_server_boss][T#1]{New I/O server boss #51} elasticsearch[Blind Faith][http_server_worker][T#1]{New I/O worker #35} elasticsearch[Blind Faith][http_server_worker][T#2]{New I/O worker #36} elasticsearch[Blind Faith][http_server_worker][T#3]{New I/O worker #37} elasticsearch[Blind Faith][http_server_worker][T#4]{New I/O worker #38} elasticsearch[Blind Faith][http_server_worker][T#5]{New I/O worker #39} elasticsearch[Blind Faith][http_server_worker][T#6]{New I/O worker #40} elasticsearch[Blind Faith][http_server_worker][T#7]{New I/O worker #41} elasticsearch[Blind Faith][http_server_worker][T#8]{New I/O worker #42} elasticsearch[Blind Faith][http_server_worker][T#9]{New I/O worker #43} elasticsearch[Blind Faith][http_server_worker][T#10]{New I/O worker #44} elasticsearch[Blind Faith][http_server_worker][T#11]{New I/O worker #45} elasticsearch[Blind Faith][http_server_worker][T#12]{New I/O worker #46} elasticsearch[Blind Faith][http_server_worker][T#13]{New I/O worker #47} elasticsearch[Blind Faith][http_server_worker][T#14]{New I/O worker #48} elasticsearch[Blind Faith][http_server_worker][T#15]{New I/O worker #49} elasticsearch[Blind Faith][http_server_worker][T#16]{New I/O worker #50} elasticsearch[Blind Faith][management][T#1] elasticsearch[Blind Faith][management][T#2] elasticsearch[Blind Faith][riverClusterService#updateTask][T#1] elasticsearch[Blind Faith][scheduler][T#1] elasticsearch[Blind Faith][transport_client_boss][T#1]{New I/O boss #17} elasticsearch[Blind Faith][transport_client_timer][T#1]{Hashed wheel timer #1} elasticsearch[Blind Faith][transport_client_worker][T#1]{New I/O worker #1} elasticsearch[Blind Faith][transport_client_worker][T#2]{New I/O worker #2} elasticsearch[Blind Faith][transport_client_worker][T#3]{New I/O worker #3} elasticsearch[Blind Faith][transport_client_worker][T#4]{New I/O worker #4} elasticsearch[Blind Faith][transport_client_worker][T#5]{New I/O worker #5} elasticsearch[Blind Faith][transport_client_worker][T#6]{New I/O worker #6} elasticsearch[Blind Faith][transport_client_worker][T#7]{New I/O worker #7} elasticsearch[Blind Faith][transport_client_worker][T#8]{New I/O worker #8} elasticsearch[Blind Faith][transport_client_worker][T#9]{New I/O worker #9} elasticsearch[Blind Faith][transport_client_worker][T#10]{New I/O worker #10} elasticsearch[Blind Faith][transport_client_worker][T#11]{New I/O worker #11} elasticsearch[Blind Faith][transport_client_worker][T#12]{New I/O worker #12} elasticsearch[Blind Faith][transport_client_worker][T#13]{New I/O worker #13} elasticsearch[Blind Faith][transport_client_worker][T#14]{New I/O worker #14} elasticsearch[Blind Faith][transport_client_worker][T#15]{New I/O worker #15} elasticsearch[Blind Faith][transport_client_worker][T#16]{New I/O worker #16} elasticsearch[Blind Faith][transport_server_boss][T#1]{New I/O server boss #34} elasticsearch[Blind Faith][transport_server_worker][T#1]{New I/O worker #18} elasticsearch[Blind Faith][transport_server_worker][T#2]{New I/O worker #19} elasticsearch[Blind Faith][transport_server_worker][T#3]{New I/O worker #20} elasticsearch[Blind Faith][transport_server_worker][T#4]{New I/O worker #21} elasticsearch[Blind Faith][transport_server_worker][T#5]{New I/O worker #22} elasticsearch[Blind Faith][transport_server_worker][T#6]{New I/O worker #23} elasticsearch[Blind Faith][transport_server_worker][T#7]{New I/O worker #24} elasticsearch[Blind Faith][transport_server_worker][T#8]{New I/O worker #25} elasticsearch[Blind Faith][transport_server_worker][T#9]{New I/O worker #26} elasticsearch[Blind Faith][transport_server_worker][T#10]{New I/O worker #27} elasticsearch[Blind Faith][transport_server_worker][T#11]{New I/O worker #28} elasticsearch[Blind Faith][transport_server_worker][T#12]{New I/O worker #29} elasticsearch[Blind Faith][transport_server_worker][T#13]{New I/O worker #30} elasticsearch[Blind Faith][transport_server_worker][T#14]{New I/O worker #31} elasticsearch[Blind Faith][transport_server_worker][T#15]{New I/O worker #32} elasticsearch[Blind Faith][transport_server_worker][T#16]{New I/O worker #33} elasticsearch[keepAlive/1.0.0.RC2] Finalizer Gang worker#0 (Parallel CMS Threads) Gang worker#1 (Parallel CMS Threads) Gang worker#0 (Parallel GC Threads) Gang worker#1 (Parallel GC Threads) Gang worker#2 (Parallel GC Threads) Gang worker#3 (Parallel GC Threads) Gang worker#4 (Parallel GC Threads) Gang worker#5 (Parallel GC Threads) Gang worker#6 (Parallel GC Threads) Gang worker#7 (Parallel GC Threads) JMX server connection timeout 80 Reference Handler RMI Scheduler(0) RMI TCP Accept-0 RMI TCP Connection(12)-172.20.10.4 Service Thread Signal Dispatcher Surrogate Locker Thread (Concurrent GC) VM Periodic Task Thread VM Thread
スレッド名が「elasticsearch」で始まるスレッドは62個あり、これがElasticsearchのアプリケーションに関連するスレッドになっています。これは、分かりやすいですね。
この一覧を眺めてみると、「http_server」「transport_client」「transport_server」という名称を含むスレッドが多いのが目立ちます。これは何でしょうか? Elasticsearchは通信周りのライブラリに、以前このブログでも紹介したNetty(ver.3)を利用しています。これらはNetty関連の通信スレッドになります。
「http_server」を含むスレッド
Elasticsearchに対するオペレーションは主にhttpで行います。Elasticsearchにアクセスするのにcurlを使った例をよく見ますが、その処理を行う箇所です。http通信周りのスレッドになります。
「transport_client」を含むスレッド
Elasticsearchがクラスタ間通信を行う際のクライアント側スレッドです。サーバ側と違い、こちらにはtimerスレッドがあります。
「transport_server」を含むスレッド
Elasticsearchがクラスタ間通信を行う際のサーバ側スレッドです。
3.Elasticsearchの入口
何か問題があったときには、ソースを読んだり、リモートデバッグすることもあると思います。そのための、入口になる箇所を探してみましよう。他のプロセスと通信処理を行っている箇所が分かれば、そこが入口になります。
Elasticsearchは通信処理にNettyを利用しています。Nettyの初期化は、org.jboss.netty.channel.ChannelPipelineFactoryを継承したクラスのgetPipelineメソッドで行います。このメソッドを実装している箇所を探してみましょう。
すると、以下のクラスが見つかりました。通信周りの設定を知りたい場合は、これらのソースコードを読むのが良いと思います。
org.elasticsearch.benchmark.transport.netty.NettyEchoBenchmark
これはElasticsearchのテストコードに入っているベンチマーク用クラスです。Elasticsearch本体とは関係ないですね。
org.elasticsearch.bulk.udp.BulkUdpService
bulk udp apiで利用される通信処理を初期化しているクラスです。この機能はデフォルトではdisabledとなっているため、先ほどのスレッド一覧にも登場していません。
リモートデバッグしたい場合は、BulkUdpServiceクラスの内部クラスHandlerのmessageReceivedメソッドにブレークポイントを設定してください。
4.Elasticsearchにリモートデバッグする方法
Windows版だとelasticsearch.bat、Linux版だとelasticsearch.in.shに、JVM引数を指定する変数JAVA_OPTSがあるので、ここにリモートデバッグに必要なオプションを追加しましょう。
例えばWindows版は、デフォルトで以下の設定になっています。
set JAVA_OPTS=%JAVA_OPTS% -XX:+HeapDumpOnOutOfMemoryError
次のようにデバッグオプションを追加しましょう。
set JAVA_OPTS=%JAVA_OPTS% -XX:+HeapDumpOnOutOfMemoryError -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8765
その後、以下の手順を実行します。
これで準備ができました。
例えば、curlでhttpリクエストを送信すると、HttpRequestHandlerのmessageReceivedメソッドに設定したブレークポイントで停止します。
さて、いかがだったでしょうか?
これをベースに、Elasticsearchのアクションやプラグインあたりの処理を追うと面白そうですね。
今回はElasticsearchの入口部分だけですが、理解やデバッグの参考になればと思います。
Acroquest Technologyでは、キャリア採用を行っています。
- 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
- 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
- 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
- OSSの開発に携わりたい。
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
キャリア採用ページ