在之前学习 Redis 的过程中, 我就是一边通过文档 / 视频学习, 一边阅读源码. 我发现两种方法可以相辅相成, 互相补充. 阅读文档可以帮助我们快速了解某个功能, 阅读源码有助于我们更深入的理解这一功能的实现及思想.
因此, 在学习 Elasticsearch 的时候我也准备采用这样的模式. 所以, 从今天开始, 我会定期更新学习 Elasticsearch 源码的收获. 在开始学习之前, 需要先把环境准备好. 所以今天就先分享一下准备环境的过程.
软件环境
Intellij Idea:2020.1 版本
- JDK 12
- Gradle 5.5
下载源码
你可以在 GitHub 中下载 release 版本或指定 tag 的源码, 地址如下.
https://github.com/elastic/elasticsearch/releases
下载好以后解压到指定目录 /
tar -xzvf Elasticsearch-7.3.1.tar.gz
也可以直接在命令行通过 Git 下载源码
Git clone Git@GitHub.com:elastic/Elasticsearch.Git
然后可以切换到你想要的版本
Git checkout v7.3.1
导入 IntelliJ IDEA
下载好源码以后, 我们来将项目导入 IDEA, 首先, 进入到项目的根目录, 执行命令
./gradlew idea
这一步是生成 IntelliJ 的项目文件, 需要下载一些依赖包, 下载的不顺利的同学可以选择将 gradle 源切换成国内的源.
切换 gradle 源
进入目录
cd ~/.gradle
新建一个名为 init.gradle 的目录, 内容如下
- allprojects {
- repositories {
- def ALIYUN_REPOSITORY_URL = 'https://maven.aliyun.com/repository/public'
- all { ArtifactRepository repo ->
- if(repo instanceof MavenArtifactRepository){
- def url = repo.url.toString()
- if (url.startsWith('https://repo1.maven.org/maven2')) {
- project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL."
- remove repo
- }
- }
- }
- maven { url ALIYUN_REPOSITORY_URL }
- }
- }
文件生成好之后, 会有如下提示
现在我们开始往 idea 中导入项目, File -> New Project From Existing Sources, 选择你的代码根目录, 然后点击 open, 之后在 Import project from external model -> Gradle, 到 idea 中, 它还会下载一些包. 下载完以后, 我们就算是导入完成了.
本地运行 Elasticsearch
将项目导入到 idea 中之后, 我们就可以尝试运行项目了, 这一步看似简单, 却是我花费时间最多的一步. 首先我们找到 server 包下的 org/Elasticsearch/Bootstrap/Elasticsearch.java, 运行其中的 main 函数.
如果你运行失败, 不要惊慌, 我们需要加一些配置.
点开 Run/Debug Configrations, 如图, 我们需要在 VM options 中加一些配置. 还需要勾选上 Include dependencies with "Provided" scope
VM options 如下
- -Des.path.home=/Users/moka/eshome
- -Des.path.conf=/Users/moka/eshome/config
- -Xms1g
- -Xmx1g
- -Dlog4j2.disable.jmx=true
- -Djava.security.policy=/Users/moka/eshome/config/Elasticsearch.policy
下面对这些参数进行一下说明
-Des.path.home: 指定 eshome 所在路径, Elasticsearch 会需要从这个路径下加载一些包, 因此, 我们需要指定一个目录, 然后把必要的模块和配置文件复制到该目录下, 你可以选择自己编译源码, 或者是从官网下载对应的二进制版本,
- tar -zxvf Elasticsearch-7.3.1-darwin-x86_64.tar.gz
- cd Elasticsearch-7.3.1
- cp -r config modules plugins /Users/moka/eshome
-Des.path.conf: 指定配置文件所在的路径名, 后续调整节点配置时, 修改其下的配置文件
-Xms1g 和 -Xmx1g 设置 JVM 堆的大小
-Dlog4j2.disable.jmx=true: 这个是 jvm.options 文件中的默认配置, 不加的话会报 "access denied" 等错误.
-Djava.security.policy: 这个也是权限问题, 配置 policy 文件路径, 内容如下
- grant{
- permission javax.management.MBeanTruxtPermission "register";
- permission javax.management.MBeanServerPermission "createMBeanServer";
- permission java.lang.RuntimePermission "createClassLoader";
- };
按照这些配置好以后, 发现还是会报错
- java.lang.NoClassDefFoundError: org/Elasticsearch/plugins/ExtendedPluginsClassLoader
- at org.Elasticsearch.plugins.PluginsService.loadBundle(PluginsService.java:494) ~[main/:?]
- at org.Elasticsearch.plugins.PluginsService.loadBundles(PluginsService.java:422) ~[main/:?]
- at org.Elasticsearch.plugins.PluginsService.<init>(PluginsService.java:146) ~[main/:?]
- at org.Elasticsearch.node.Node.<init>(Node.java:303) ~[main/:?]
- at org.Elasticsearch.node.Node.<init>(Node.java:246) ~[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:323) ~[main/:?]
- at org.Elasticsearch.Bootstrap.Elasticsearch.init(Elasticsearch.java:121) ~[main/:?]
- at org.Elasticsearch.Bootstrap.Elasticsearch.execute(Elasticsearch.java:112) ~[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:92) ~[main/:?]
- at org.Elasticsearch.Bootstrap.Elasticsearch.main(Elasticsearch.java:85) ~[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 的报错, 网上有同学说是勾选 Include dependencies with "Provided" scope, 我试了一下没什么效果. 然后把 server 包下的 build.gradle 文件修改一下解决了问题.
找到
compileOnly project(':libs:elasticsearch-plugin-classloader')
修改为
compile project(':libs:elasticsearch-plugin-classloader')
改完之后再次运行, 会有一个空指针报错, 报错位置是
server/src/main/java/org/Elasticsearch/node/InternalSettingsPreparer.java:119
这里是因为我没有设置 node.name, 在 Elasticsearch.YAML 文件中设置一下就可以了.
现在再点击 Run/Debug , 就可以成功运行了.
远程调试
本地调试的另一种方法就是远程 debug.
首先, 我们进入到下载的一个稳定版本的 Elasticsearch 目录, 在 bin/Elasticsearch 文件中加上一行代码
-agentlib:jdwp=transport=dt_socket,server=y,address=8888,suspend=y \
加上之后的代码如下:
- if ! echo $* | grep -E '(^-d |-d$| -d |--daemonize$|--daemonize )'> /dev/null; then
- exec \
- "$JAVA" \
- $ES_JAVA_OPTS \
- -agentlib:jdwp=transport=dt_socket,server=y,address=8888,suspend=y \
- -Des.path.home="$ES_HOME" \
- -Des.path.conf="$ES_PATH_CONF" \
- -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \
- -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \
- -Des.bundled_jdk="$ES_BUNDLED_JDK" \
- -cp "$ES_CLASSPATH" \
- org.Elasticsearch.Bootstrap.Elasticsearch \
- "$@"
- else
- exec \
- "$JAVA" \
- $ES_JAVA_OPTS \
- -Des.path.home="$ES_HOME" \
- -Des.path.conf="$ES_PATH_CONF" \
- -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \
- -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \
- -Des.bundled_jdk="$ES_BUNDLED_JDK" \
- -cp "$ES_CLASSPATH" \
- org.Elasticsearch.Bootstrap.Elasticsearch \
- "$@" \
- <&- &
- retval=$?
- pid=$!
- [ $retval -eq 0 ] || exit $retval
- if [ ! -z "$ES_STARTUP_SLEEP_TIME" ]; then
- sleep $ES_STARTUP_SLEEP_TIME
- fi
- if ! ps -p $pid> /dev/null ; then
- exit 1
- fi
- exit 0
- fi
- exit $?
然后我们执行./Elasticsearch, 会出现如下信息, 说明 Elasticsearch 在监听 8888 端口.
现在我们到 IDEA 中添加一个 Remote Run
接着进行端口配置.
然后就可以选择这个 Remote 来进行 Debug 了. 当控制台出现
Connected to the target VM, address: 'localhost:8888', transport: 'socket'
说明连接成功了.
我们来实验一下, 在这个位置打一个断点
server/src/main/java/org/Elasticsearch/REST/action/cat/RestHealthAction.java:54
然后在浏览器地址栏中输入
http://localhost:9200/_cat/health
如果进入断点, 说明我们已经可以成功 Debug 了.
总结
工欲善其事, 必先利其器. 在阅读源码之前, 我们首先需要搭建好环境, 本文我们介绍了两种方法, 一种是直接在 IDEA 中启动 Elasticsearch , 另一种是 Debug 远程的 Elasticsearch. 其中第二种方法, 相对比较简单, 推荐大家使用.
来源: https://www.cnblogs.com/Jackeyzhe/p/13352543.html