前言
大家好,我是一野,19年非科班本科毕业,大学期间自学编程,有幸成为一名Android前后端开发者,没错我就是一名野开发,哈哈!目前和朋友成立了一家科技公司,一起创业做自己的一款APP产品。使用elasticsearch已经有一段时间了,作为一个Java为第一语言的developer(其实目前我也只会Java),很幸运能接触到这样优秀的产品,为什么这么说呢?es的优点就不用我在此重复了,我说说我的个人想法吧。虽然目前我是在做原生Android相关开发,但我觉得我必须要在一个细分领域深入研究,显然我所说的细分领域便是指的数据检索。为什么是这个领域呢,因为随着互联网的发展,特别是5G时代的到来,数据将爆炸试的增长,每一个互联网产品都将面临数据检索这个问题。马云说阿里是一家数据公司,谁拥有大数据,谁将拥有未来。正如罗胖所说,数据不再是资源,而将是土壤。它孕育着科技,也滋养着商业,而最终呢,它将是未来决定一切的力量。目前,我对大数据方面的知识知之甚少,仅仅接触过ES,也只是了解到皮毛,像Hadoop等大数据相关技术也并不了解(当然后面肯定是要去学习的),目前ElasticStack作为一整套数据处理、分析、检索 技术栈,不正是我学习大数据技术最好的切入点吗?在此我由衷感谢Elastic公司能开发出这样强大好用的开源产品,降低了我们进入大数据领域的学习成本,在我看来这就是一个机会。
受冠状病毒影响,春节在家呆了一个多月,也是这一个多月我完整的读完了田雪松老师写的《ElasticStack应用宝典》,同时也跟着阮一鸣老师在极客时间出品的“Elasticsearch核心技术与实战”系列课程完整学习了一遍,这两个都是基于ElasticStack7而出品的内容。通过他们,我算是大致了解了ES技术栈,同时对其也更加深刻的理解及使用和部署、运维,至此也算是ES入门了吧。二月底,回到公司,趁闲暇时间,我决定得深入了解ES,于是买了一本,由铭毅老师推荐的《Elasticsearch源码解析与优化实战》张超著,基于es6。但是没想到,在本书的第二章搭建源码环境时就遇到了一些小麻烦,几经周折,终于解决了,所以想分享给大家。
软件环境
- Intellij idea:2019.3
- Gradle 5.5
- JDK 12.0.2
- macOS 10.15.4
准备工作
- 下载elasticsearch7.3.2源码:https://github.com/elastic/elasticsearch/releases?after=v7.3.2
- 下载elasticsearch7.3.2发行版:https://www.elastic.co/downloads/past-releases/elasticsearch-7-3-2
- 下载Gradle 5.5:https://services.gradle.org/distributions/
- 下载jdk 12:https://www.oracle.com/cn/java/technologies/javase-downloads.html
安装:
- gradle和jdk,mac用户可直接使用homebrew下载即可,Windows用户可以根据我上面提供的下载地址下载。mac用brew安装后无需配置其环境变量,因为brew会自动使用symlink来管理,这个东西我后面会出专门的文章讲解,这里无需感到疑惑。
- elasticsearch可以使用git克隆到本地,也可以使用我上面提供的下载地址,下载压缩文件并解压到自定义的路径下面。
注意:
- elasticsearch7.3.2版本源码编译环境,gradle 5.5版本及以上,JDK 12及以上。
- es的源码版本和发型版本必须一致,原因是在运行源码时需要自己去配置es的config和modules,此处直接使用发行版本的即可
- 具体各个版本ES源码的编译环境要求可以从下载的源码包中获取到,具体路径如下:elasticsearch-7.3.2/buildSrc/src/main/resources/minimumGradleVersion、minimumRuntimeVersion、minimumCompilerVersion,分别表示gradle、运行时jdk、编译时jdk最低版本要求。
编译源码
好了,既然环境都准备好了,我们就开始编译源码吧!
打开命令行进入到源码的根目录中,直接执行 ./gradlew idea 命令(早期版本可能需要执行 gradle idea),当命令行打印BUILD SUCCESSFUL 的字样就算完成了,此时你会发现源码根目录会多出一个elasticsearch-7.3.2.ipr的文件,该文件是创建idea项目时自动创建来保存项目的配置信息的文件。整个过程会花5-10分钟,甚至更久,希望小伙伴们耐心等待了。
导入工程到idea
此时导入之前编译为idea项目的源码进idea即可,进入工程后,等gradle加载完必要的依赖文件即可,如下图:该工程的启动入口位于:elasticsearch-7.3.2/server/src/main/java/org/elasticsearch/bootstrap/Elasticsearch.java类的main函数,此时直接运行肯定会报错,因为还没有配置在启动时必要的配置文件。
配置工程
点击 run——>EditConfigurations打开配置界面,新添加一个application运行的configuration,如下:- 这里需要特殊说明一下 VM options具体应该怎么配置,如下:
-Des.path.home=/Users/abley/Java/elasticsearch-7.3.2/eshome
-Des.path.conf=/Users/abley/Java/elasticsearch-7.3.2/eshome/config
-Dlog4j2.disable.jmx=true
-Djava.security.policy=/Users/abley/Java/elasticsearch-7.3.2/eshome/config/elasticsearch.policy
-Des.path.plugins=/Users/abley/Java/elasticsearch-7.3.2/eshome/plugins
- 其中的eshome是自定义的配置文件夹,我将其放入到es源码根目录中。需要将es对应发行版中的config、modules、plugins目录拷贝到eshome目录中。同时,还需要在config目录中增加一个配置文件,elasticsearch.policy,其中的内容如下:
grant {
permission javax.management.MBeanTruxtPermission “register”;
permission javax.management.MBeanServerPermission “createMBeanServer”;
permission java.lang.RuntimePermission “createClassLoader”;
};
- 好了,通过以上配置后,就可以正常开启这个工程了,网上所以资料到此也就结束了。真的是这样吗,很遗憾,我还是无法启动这个工程,它始终会包空指针异常,那应该怎么解决呢,下面才是我想分享给大家的,毕竟上面的内容网上都能轻易找到。
干货时刻
应该是在新版本中的问题,异常如下:
Exception in thread "main” java.lang.NullPointerException
at org.elasticsearch.node.InternalSettingsPreparer.checkSettingsForTerminalDeprecation(InternalSettingsPreparer.java:119)
at org.elasticsearch.node.InternalSettingsPreparer.prepareEnvironment(InternalSettingsPreparer.java:91)
at org.elasticsearch.bootstrap.Bootstrap.createEnvironment(Bootstrap.java:267)
at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:306)
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.
点击报错定位到源码位置如下:分析
应该是output.get(settiong) 为空,于是乎断点伺候,果然如此,output是一个map集合,发现它的node.name确实为null,断点如图:跟进getenv(String name)方法发现是jdk内部读取环境变量有关的逻辑,看得我也是一头雾水,这目前也已经超出了我的能力范围,就此打住,有兴趣的朋友可以自行研究下,到时候记得也告诉在下学习一下,谢谢。
解决
难道就没办法解决了吗?当然不是!解决方案有两种。
- 方案一:如果你稍微细心你会发现,报空指针的这个方法上方的注释描述如下:
Checks all settings values to make sure they do not have the old prompt settings. These were deprecated in 6.0.0.This check should be removed in 8.0.0.
字面翻译如下:
检查所有设置值,以确保它们没有旧的提示设置。这些在6.0.0中已弃用。此检查应在8.0.0中删除。
现在明白了吧!你只要将该方法注释掉即可。但有一个问题,它没有默认nodeName,这其实是有问题的。所以我推荐使用第二种解决方案。
- 方案二:在配置文件中指定nodeName值
及在 elasticsearch-7.3.2/eshome/config/elasticsearch.yml文件中指定一个自定义的nodeName即可,此后es在运行时就可以加载到该nodeName而不至于报空指针异常了
再遇异常
本以为大功告成可以一头扎进es源码中无法自拔时,什么鬼?还来!再遇异常,也只能干呗,异常代码如下:
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:314) ~[main/:?]
at org.elasticsearch.node.Node.<init>(Node.java:258) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap$5.<init>(Bootstrap.java:221) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:221) ~[main/:?]
at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:349) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:159) ~[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) ~[elasticsearch-cli-7.3.2-SNAPSHOT.jar:?]
at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-7.3.2-SNAPSHOT.jar:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:115) ~[main/:?]
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[main/:?]
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.plugins.ExtendedPluginsClassLoader
at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[?:?]
at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[?:?]
Caused by: java.lang.ClassNotFoundException: org.elasticsearch.plugins.ExtendedPluginsClassLoader
分析与解决
我开动大脑强行分析,。。。。无果!!!于是乎,去网上找了一圈还真找到了解决方案,如下:
在源码的server模块下的 build.gradle 中82行 compileOnly project(':libs:elasticsearch-plugin-classloader') ,将compileOnly改为compile即可。这里解释下,compileOnly是指该依赖只在编译时有效,运行时无效。
既然运行时需要这个包,为啥还用compileOnly!
至此,现在终于可以愉快的运行es源码了,哈哈!后记
前面说到我和朋友们在创业做一款APP,这款APP叫“蚂蚁同行”,初衷是曝光骗子,让社会更加诚信美好。里面有完备的IM聊天服务,真正公开透明的捐赠系统、媲美地方电视台的“焦点”模块、基于地理位置的信息检索与交互等等好玩又充满正能量的功能。这是我们的下载地址:http://www.mytx.tech,同时也可在百度应用商店搜索到,目前正在办理软件著作权(这里顺带吐槽下,软著真是太黑了,我觉得315就因该好好打打,给钱2W,两天就可以办下来,不给钱得要好几个月,我打电话给相关部门咨询软著办理事宜,相互推诿,给我个根本打不通的电话叫我咨询,得了,最终花了500,网上找了代提交的中介,说5月8号下来,在此提醒下需要办理软著的小伙伴,最好在项目进行的同时就申请,不然会很慢很慢~),等软著下来了我们会上架到各大APPStore,感兴趣的朋友可以了解下,觉得我们做的事情有意义也欢迎广大朋友加入我们。同时在ES的学习中大家可以相互探讨,我的个人wx:abley1874