关于elasticsearch:讲得最明白的Elasticsearch源码调试环境搭建教程

4次阅读

共计 6920 个字符,预计需要花费 18 分钟才能阅读完成。

写在后面

应用 elasticsearch(以下简称 ES)也有挺长时间了,始终想找机会深刻源码钻研下。我看源码有个习惯,就是肯定要运行起来。不是只把源码下载下来看看就行的。

搭建整个调试环境简直花了一整天的功夫,这里记录下,心愿能帮到须要的人。

环境介绍

  • MAC Mojave 零碎
  • idea 2019.2
  • JDK 版本:jdk12
  • elasticsearch 版本:7.1.0
  • gradle 版本:5.2.1

源码下载

能够间接去 github 下载指定 release 版本的源码,也能够间接 clone 目前的 master 分支,而后 checkout 到一个特定的版本。

git clone https://github.com/elastic/elasticsearch.git

切换到指定公布版本

git checkout v7.x

我个别会 fork 一份到本人的仓库,这样看代码的时候写的正文能够提交到本人的仓库。

配置 gradle 和 jdk 的环境

具体的 SDK 和 gradle 的装置步骤不在这里开展了,自行搜寻吧。

我本人的电脑是通过 sdkman 治理不同的 JDK 版本,能够同时有多个 JDK 版本存在一台主机随时切换应用。

这里须要重点说下 ES 对 JDK 和 Gradle 的版本要求。ES 运行和编译所须要的 JDK 版本是须要离开探讨的。

ES 运行只有 8 或者以上就能够了,我本人就是本地用 JDK8 运行 ES 实例,尽管启动过程中会有相干正告版本低,然而不影响应用。比方我会收到相似上面的正告:

future versions of Elasticsearch will require Java 11; your Java version from [/Users/xxxx/.sdkman/candidates/java/8.0.242-amzn/jre] does not meet this requirement

如果是编译源码,对 JDK 的版本要求又高一点。个别在源码根目录下的 contributing.md 文件会有对于编译某个版本的 ES 须要的 JDK 的版本要求,比方我编译的版本,有这么一段阐明:

JDK 12 is required to build Elasticsearch. You must have a JDK 12 installation with the environment variable JAVA_HOME referencing the path to Java home for your JDK 12 installation. 

gradle 的版本要求,咱们也能够在

源码根目录 /buildSrc/src/main/resources/minimumGradleVersion

这个文件里找到。另外还有两个文件:minimumRuntimeVersion、minimumCompilerVersion,别离示意运行时 jdk、编译时 jdk 最低版本要求。

源码导入 idea 编译

首先进入源码的根目录下,执行以下命令

./gradlew idea

这个命令是配置工程依赖的环境,在导入源码到 ES 之前做的。这个命令执行的工夫有点长,我本人的环境跑了 10 多分钟。执行完后,最初会看到相似上面的输入:

Generated IDEA project at file:///Users/ponyma/idea_project/elasticsearch/elasticsearch.ipr

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 16m 47s
351 actionable tasks: 319 executed, 32 up-to-date

而后 idea 导入源码工程,导入的流程是:

File -> New Project From Existing Sources 抉择你下载的 Elasticsearch 根目录,而后点 open,之后 Import project from external model -> Gradle , 选中 Use auto-import。

期待编译,也要几分钟。

倡议配置上面这个环境变量,因为 ES 在编译的两头过程会依赖这个,没有这个配置的话可能会看到相干的正告。

JAVA9_HOME=/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
export JAVA9_HOME

调试代码

调试源码有两种形式。

一种是应用 gradle 的近程调试模式

gradlew run --debug-jvm

开始 debug 模式运行,等几分钟后启动结束,呈现如下图所示:

在 IDEA 里点击 Run -> Attach to Process,抉择刚刚启动的 ES 过程连贯。

如果第一步 debug 运行失败了,就 gradlew clean 下多试几次。

近程调试原理相当于在服务器启动了一个 ES 实例,只不过这个实例就是咱们本地。这样你的源码编译完启动会读取 ES 默认的配置。

启动后,咱们在浏览器输出

http://localhost:9200

应该能够看到相似如下的信息:

{
  "name" : "node-0",
  "cluster_name" : "distribution_run",
  "cluster_uuid" : "ocg6NwKBRZyeg7YqmCyGUA",
  "version" : {
    "number" : "7.1.1-SNAPSHOT",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "7a013de",
    "build_date" : "2020-08-14T22:58:40.066107Z",
    "build_snapshot" : true,
    "lucene_version" : "8.0.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

如果提醒你输出用户名明码,就输出elastic/password

还有一种形式能够调试

咱们间接运行源码的 main 函数,在 server 模块的

org.elasticsearch.bootstrap.Elasticsearch

如果你间接运行,发现会报上面这个谬误:

ERROR: the system property [es.path.conf] must be set

这是通知咱们须要指定一个蕴含配置文件的目录,咱们能够间接下载一个发行版的 ES,而后在 idea 的 VM Options 指定这个这个发行版 ES 的 config 目录,而后同时须要指定es.path.home,配置如下:

-Des.path.conf=/usr/local/elk/elasticsearch-7.1.0/config
-Des.path.home=/usr/local/elk/elasticsearch-7.1.0

下面的门路依据本人的理论状况批改。

而后运行,有报错:

Exception in thread "main" java.lang.NullPointerException
    at org.elasticsearch.node.InternalSettingsPreparer.checkSettingsForTerminalDeprecation(InternalSettingsPreparer.java:123)
    at org.elasticsearch.node.InternalSettingsPreparer.prepareEnvironment(InternalSettingsPreparer.java:91)
    at org.elasticsearch.bootstrap.Bootstrap.createEnvironment(Bootstrap.java:257)
    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:290)
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159)
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150)
    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86)
    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124)
    at org.elasticsearch.cli.Command.main(Command.java:90)
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115)
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92)
Refer to the log for complete error details.

debug 跟到源码里,发现是 node.name 这值是空导致的,那简略,在配置文件里加上就行了。批改elasticsearch.yml,加上上面这个:

node.name: node-1

而后持续运行,what? 持续报错:

main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
    at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:358)
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.checkMBeanTrustPermission(DefaultMBeanServerInterceptor.java:1805)
    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:318)
    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
    ...

这是 log4j JMX 报错了。JMX 是一个管理应用程序的接口,log4j 提供了对 JMX 的反对,实现了近程动静批改配置等性能。

这个其实不是 ES 的外围性能,既然报错了,罗唆就把它敞开吧。

-Dlog4j2.disable.jmx=true

持续运行,还是报错:

[2020-08-16T09:19:42,833][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [node-1] fatal error in thread [main], exiting
java.lang.NoClassDefFoundError: org/elasticsearch/plugins/ExtendedPluginsClassLoader
    at org.elasticsearch.plugins.PluginsService.loadBundle(PluginsService.java:545) ~[main/:?]
    at org.elasticsearch.plugins.PluginsService.loadBundles(PluginsService.java:471) ~[main/:?]
    at org.elasticsearch.plugins.PluginsService.<init>(PluginsService.java:163) ~[main/:?]
    at org.elasticsearch.node.Node.<init>(Node.java:308) ~[main/:?]
    at org.elasticsearch.node.Node.<init>(Node.java:252) ~[main/:?]
    at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:211) ~[main/:?]
...

这个谬误我查了挺久,跟 idea 环境无关,做了两处批改得以解决。一个是

idea > preferences > Build, Execution, Deployment > Build Tools > Gradle

Build and run using gradle 改成 Build and run using IntelliJ IDEA

另一处批改是 Edit Configuration,找到Include dependencies with Provided scope,选中。

运行,接着报错:

2020-08-16T09:29:32,101][WARN][o.e.b.ElasticsearchUncaughtExceptionHandler] [node-1] 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:163) ~[main/:?]
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:150) ~[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:115) ~[main/:?]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[main/:?]
    ...

这个问题查了一些材料,解决方案如下:

在发行版的 config 目录下新建 java.policy 文件,填入上面内容:

grant {permission java.lang.RuntimePermission "createClassLoader";};

而后在 VM options 退出 java.security.policy 的设置,指向该文件即可

-Djava.security.policy=/usr/local/elk/elasticsearch-7.1.0/config/java.policy

好了,终于运行胜利了!在浏览器里输出

http://localhost:9200

能够看到集群的信息了。

而后咱们就能够欢快的 debug 了!

正文完
 0