前言
想深刻理解 Elasticsearch,閱讀它的源碼是頗有必要的,一來能夠了解它內部的具體實現,有助於調優,二來能夠了解優秀開源項目的代碼架構,提升咱們的代碼架構能力等css
閱讀Elasticsearch源碼的第一步是搭建調試環境,而後做者在這個過程當中遇到不少麻煩,在網上找不到想要的答案,歷經千辛最後一一解決,因此記錄下,幫助有須要的童鞋html
軟件環境
操做系統:win7java
Elasticsearch 源碼版本: 6.3.2node
JDK版本: 10.0.2nginx
Gradle版本: 4.7git
Intellij Idea版本: 2018.2github
環境準備及工程導入
1.安裝JDK
Elasticsearch 6.3.2須要JDK1.9編譯,不然後面步驟會報錯。bootstrap
Java SE Downloads 地址:
http://www.oracle.com/technetwork/java/javase/downloads/index.htmlwindows
做者裝的是 JDK 10.0.2瀏覽器
2.下載Elasticsearch源碼,而且切換到6.3.2分支
Elasticsearch github源碼託管地址:
https://github.com/elastic/elasticsearch.git
git checkout v6.3.2
也可直接下載源碼包,地址在 https://github.com/elastic/elasticsearch/releases
3.下載gradle的安裝包
查看 elasticsearch\gradle\wrapper\gradle-wrapper.properties
發現以下配置:
distributionUrl=https://services.gradle.org/distributions/gradle-4.5-all.zip
Elasticsearch 6.3.2須要安裝gradle-4.5,官方下載地址:
https://services.gradle.org/distributions/gradle-4.5-all.zip
注意:因爲國內網速問題,爲了加快速度,進行第4步操做
4.拷貝文件
將下載的gradle-4.5-all.zip包放到 elasticsearch\gradle\wrapper
目錄下,
確保和 elasticsearch\gradle\wrapper\gradle-wrapper.properties
在同級目錄,
而後修改 elasticsearch\gradle\wrapper\gradle-wrapper.properties
配置以下:
distributionUrl=gradle-4.5-all.zip
5.修改源碼Maven倉庫地址
國內下載國外倉庫的jar包速度慢,須要替換Maven地址,設置爲本地或者國內可用的Maven倉庫。
須要修改下列文件的 maven URL 配置:
elasticsearch\benchmarks\build.gradle
elasticsearch\client\benchmark\build.gradle
修改源碼中上面build.gradle文件裏面的repositories-maven-url
的值,
配置爲可用的倉庫地址,譬如修改成阿里雲maven地址 http://maven.aliyun.com/nexus/content/groups/public/
,修改示例以下:
buildscript {
repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
}
}
6.修改全局Maven倉庫地址
在USER_HOME/.gradle/
下面建立新文件 init.gradle
,輸入下面的內容並保存。
allprojects{
repositories {
def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/'
all {
ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://repo.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')) {
project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
remove repo
}
}
}
maven {
url REPOSITORY_URL
}
}
}
其中USER_HOME/.gradle/
是本身的gradle安裝目錄,示例值:C:\Users\Administrator\.gradle
,
若是沒有.gradle
目錄,可用本身建立,或者先執行第7步,等gradle安裝後再回來修改。
上面腳本把url匹配到的倉庫都替換成了阿里雲的倉庫,
若是有未匹配到的致使編譯失敗,可用本身仿照着添加匹配條件。
7.gradle編譯源碼
windows運行cmd,進入DOS命令行,而後切換到elasticsearch源碼的根目錄,執行以下命令,把elasticsearch編譯爲 idea 工程:
gradlew idea
編譯失敗則按照錯誤信息解決問題,可用使用以下命令幫助定位問題:
gradlew idea -info
gradlew idea -debug
通常是Maven倉庫地址不可用致使jar包沒法下載,從而編譯失敗,此時請參考步驟5和6修改相關的倉庫地址。
編譯成功後打印日誌:
BUILD SUCCESSFUL in 1m 23s
8. idea 導入elasticsearch工程
idea 中 File -> New Project From Existing Sources
選擇你下載的 Elasticsearch 根目錄,而後點 open
,以後 Import project from external model -> Gradle
, 選中 Use auto-import
, 而後就能夠了
導入進去後,gradle 又會編譯一遍,須要等一會,好了以後以下:
![IDEA導入Elasticsearch6.3.2以後](http://static.javashuo.com/static/loading.gif)
運行,開始 solve error 模式
前面的步驟都挺順利,接下來遇到的 ERROR & EXCEPTION 讓做者耗費了好幾天,心力交瘁,好在最終運行成功
在 elasticsearch/server/src/main/org/elasticsearch/bootstrap
下找到Elasticsearch的啓動類 Elasticsearch.java
,打開文件,右鍵 Run Elasticsearch.main()
,運行main方法
一、 報錯以下:
ERROR: the system property [es.path.conf] must be set
這是須要配置 es.path.conf 參數,咱們先在 elasticsearch 源碼目錄下新建一個 home 目錄,而後在 https://www.elastic.co/downloads/elasticsearch
下載一個同版本號的 Elasticsearch6.3.2 發行版,解壓,將 config 目錄拷貝到 home 目錄中
而後打開 Edit Configurations
,在 VM options
加入以下配置:
![Edit Configurations](http://static.javashuo.com/static/loading.gif)
-Des.path.conf=D:\elasticsearch-6.3.2\home\config
再次運行 Run Elasticsearch.main()
二、報錯以下:
Exception in thread "main" java.lang.IllegalStateException: path.home is not configured
at org.elasticsearch.env.Environment.<init>(Environment.java:103)
...
須要配置 path.home
這個參數,在 VM options 中添加以下配置:
-Des.path.home=D:\elasticsearch-6.3.2
再次RUN
三、報錯以下:
2018-08-22 15:07:17,094 main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
...
Caused by: java.nio.file.NoSuchFileException: D:\elasticsearch-6.3.2\modules\aggs-matrix-stats\plugin-descriptor.properties
...
在 VM options
中把 path.home
的值修改成以下:
-Des.path.home=D:\elasticsearch-6.3.2\home
而後把 ES6.3.2 發行版中的 modules
文件夾複製到 home
目錄下,而後再次RUN
四、報錯以下:
2018-08-22 15:12:29,876 main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
...
在 VM options
中加入
-Dlog4j2.disable.jmx=true
一、二、三、4 的配置最終以下:
![image](http://static.javashuo.com/static/loading.gif)
再次RUN
五、報錯以下:
[2018-08-23T00:53:17,003][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [] fatal error in thread [main], exiting
java.lang.NoClassDefFoundError: org/elasticsearch/plugins/ExtendedPluginsClassLoader
at org.elasticsearch.plugins.PluginsService.loadBundle(PluginsService.java:632) ~[main/:?]
at org.elasticsearch.plugins.PluginsService.loadBundles(PluginsService.java:557) ~[main/:?]
at org.elasticsearch.plugins.PluginsService.<init>(PluginsService.java:162) ~[main/:?]
at org.elasticsearch.node.Node.<init>(Node.java:311) ~[main/:?]
at org.elasticsearch.node.Node.<init>(Node.java:252) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:213) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:213) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:326) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:127) ~[main/:?]
at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[main/:?]
at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[main/:?]
at org.elasticsearch.cli.Command.main(Command.java:90) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:86) ~[main/:?]
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.plugins.ExtendedPluginsClassLoader
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582) ~[?:?]
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190) ~[?:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:499) ~[?:?]
... 15 more
這個問題其實不算真正的問題,可是提及來挺可笑,爲了解決這個問題耗費了做者好幾天,當最後發現問題所在的時候,啼笑皆非 ~_~ 正是所謂的 踏破鐵鞋無覓處,得來全不費工夫
解決方法: 打開 IDEA Edit Configurations
,給 Include dependencies with Provided scope
打上勾便可解決,很簡單吧!!
![image](http://static.javashuo.com/static/loading.gif)
繼續RUN,又來一個 Exception
六、報錯以下:
[2018-08-23T01:13:38,551][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createClassLoader")
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:140) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:127) ~[main/:?]
at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[main/:?]
at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[main/:?]
at org.elasticsearch.cli.Command.main(Command.java:90) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:86) ~[main/:?]
Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createClassLoader")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[?:?]
at java.security.AccessController.checkPermission(AccessController.java:895) ~[?:?]
at java.lang.SecurityManager.checkPermission(SecurityManager.java:335) ~[?:?]
at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:397) ~[?:?]
...
Exception: java.security.AccessControlException thrown from the UncaughtExceptionHandler in thread "Thread-2"
這個問題也找了挺久,最終才發現解決方法(兩種):
第一種: 在 home/config
目錄下新建 java.policy
文件,填入下面內容
grant {
permission java.lang.RuntimePermission "createClassLoader";
};
而後在 VM options
加入 java.security.policy
的設置,指向該文件便可
-Djava.security.policy=D:\elasticsearch-6.3.2\home\config\java.policy
第二種: 就是在 %JAVA_HOME%/conf/security
目錄下(JDK10是這個路徑,以前的版本不肯定),個人目錄是 C:\Program Files\Java\jdk-10.0.2\conf\security
,打開 java.policy
文件,在 grant
中加入下面這句,賦予權限
permission java.lang.RuntimePermission "createClassLoader";
效果以下:
![java.policy](http://static.javashuo.com/static/loading.gif)
![createClassLoader](http://static.javashuo.com/static/loading.gif)
再RUN,此次可終於運行起來了!!!
來看一下效果,瀏覽器訪問 http://localhost:9200/
![image1](http://static.javashuo.com/static/loading.gif)
瀏覽器訪問 http://localhost:9200/_cat/health?v
![image](http://static.javashuo.com/static/loading.gif)
一切正常,終於能夠愉快的 DEBUG 源碼啦!!!
另外一種源碼調試方式:遠程調試
若是上面第五個報錯以後解決不了沒法繼續進行,能夠選擇這種方式:
在 Elasticsearch 源碼目錄下打開 CMD,輸入下面的命令啓動一個 debug 實例
gradlew run --debug-jvm
若是啓動失敗可能須要先執行 gradlew clean
再 gradlew run --debug-jvm
或者 先退出 IDEA
![image](http://static.javashuo.com/static/loading.gif)
在 IDEA 中打開 Edit Configurations
,添加 remote
![image](http://static.javashuo.com/static/loading.gif)
配置 host 和 port
![image](http://static.javashuo.com/static/loading.gif)
點擊 debug,瀏覽器訪問 http://localhost:9200/
,便可看到ES返回的信息
隨機調試一下, 打開 elasticsearch/server/src/main/org/elasticsearch/rest/action/cat
下的 RestHealthAction
類,在第 54 行出設置一個斷點,而後瀏覽器訪問 http://localhost:9200/_cat/health
,能夠看到斷點已經捕獲到該請求了
![image](http://static.javashuo.com/static/loading.gif)
運行成功,能夠開始設置斷點進行其餘調試
其餘可能遇到的問題
1. 錯誤信息以下
JAVA8_HOME required to run tasks gradle
配置環境變量 JAVA8_HOME
,值爲 JDK8 的安裝目錄
2. 錯誤信息以下
[2018-08-22T13:07:23,197][INFO ][o.e.t.TransportService ] [EFQliuV] publish_address {10.100.99.118:9300}, bound_addresses {[::]:9300}
[2018-08-22T13:07:23,211][INFO ][o.e.b.BootstrapChecks ] [EFQliuV] bound or publishing to a non-loopback address, enforcing bootstrap checks
ERROR: [1] bootstrap checks failed
[1]: initial heap size [268435456] not equal to maximum heap size [4273995776]; this can cause resize pauses and prevents mlockall from locking the entire heap
[2018-08-22T13:07:23,219][INFO ][o.e.n.Node ] [EFQliuV] stopping ...
2018-08-22 13:07:23,269 Thread-2 ERROR No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'log4j2.debug' to show Log4j2 internal initialization logging.
Disconnected from the target VM, address: '127.0.0.1:5272', transport: 'socket'
在 Edit Configurations
的 VM options
加入下面配置
-Xms2g
-Xmx2g
歡迎訪問個人我的博客:http://laijianfeng.org
參考文檔:
Eclipse導入Elasticsearch源碼
Elasticsearch源碼分析—環境準備(一)
渣渣菜雞的 ElasticSearch 源碼解析 —— 環境搭建
教你如何在 IDEA 遠程 Debug ElasticSearch
本文分享自微信公衆號 - 小旋鋒(whirlysBigData)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。