记一次elasticSearch7.3.x+springboot配置+排错过程

最近在我的一个资源站(www.kuizii.com)中做一个检索功能接入了ElasticSearch.原因众所周边,众所周知,ES(简称)对内容站的检索比操作数据库快上很多在数据量巨大的情况下,数据量小没必要,链路越多,依赖的三方中间件越多,所产生的不稳定因互也会增加。

大家应该知道ES比起原生Luncene多了一次封装,为了适配luncene各版本以及es程序的各版本(不同版本往上往下都没有很多的兼容),同时官方的sdk有众多的三方依赖,比如netty,log4j,在搭建使用springboot+es时往往会出现很多错误,Spring的ioc特性给大家带来好处的同时还带来一堆问题,比如依赖组件的版本冲突,基本上都得编译时再会报出一堆错误堆栈信息让人去排查。

百度上虽然一堆文章,还是大多陈旧以及千篇一律。看似轻松搭建,实际可能会遇到不少问题。

以上废话

先来一遍开发流程

1.从https://www.elastic.co/cn/elasticsearch下载 7.3.2版本。安装(或解压)并启动。(如果你ES恰好是6.4.3,哪么与本文的异常无关)

2.添加MAVEN的引用,引用最新(平时理所当然以为最新版本可以满足,所以引用写该文章时最新版本 2.2.5)



    org.springframework.boot
    spring-boot-starter-data-elasticsearch
    2.2.5.RELEASE

3.实现  ElasticsearchRepository 接口,用以直接操作数据

public interface BookRepository extends ElasticsearchRepository {

    //Page findByNameOrContent(String name, Pageable pageable);
}

4.在Service层或Controller层或其它哪一层注入XXXRepository 就可以使用了。

@Service
public class BookSerivceImpl implements BookService {

    @Autowired
    BookRepository bookRepository;

    @Override
    public Optional findById(String id) {
        return bookRepository.findById(id);
    }

    @Override
    public ResourceDto save(ResourceDto book) {
        return bookRepository.save(book);
    }

    @Override
    public void delete(ResourceDto book) {
        bookRepository.delete(book);
    }
}

DEBUG,发现编译报错。注入失败

Description:

Field bookRepository in com.kuizii.ebook.core.elastic.search.service.impl.BookSerivceImpl required a bean of type 'com.kuizii.ebook.core.elastic.search.repository.BookRepository' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)

像这样的问题经常见,出现这种问题无论是否跟本文内容有关   大家一定要先想到这是因为spring容器没有扫描(其实是反射)到要创建的对象。这种原因大多是因为一个,未指定扫描位置,添加下面一句 @EnableElasticsearchRepositories(basePackages=xxx)

@SpringBootApplication
@MapperScan(basePackages = {"com.kuizii.ebook.core.dao"})//mybatis扫描组件用的
@ComponentScan(basePackages = {"com.kuizii"}) //spring扫描组件用的
@EnableElasticsearchRepositories(basePackages = "com.kuizii.ebook.core.elastic") //这里,es扫描组件用的,添加这一句
public class EbookStarterApplication{

    public static void main(String[] args) {

       
       SpringApplication.run(EbookStarterApplication.class,args);
    }
}

接下来 继续编译,诶,又报错

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'elasticsearchClient' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method 'elasticsearchClient' threw exception; nested exception is java.lang.NoSuchFieldError: LUCENE_6_0_0
	at ............
略N个堆栈信息
Caused by: java.lang.NoSuchFieldError: LUCENE_6_0_0
	at org.elasticsearch.Version.(Version.java:47) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.logging.DeprecationLogger.(DeprecationLogger.java:158) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.unit.ByteSizeValue.(ByteSizeValue.java:38) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.common.network.NetworkService.(NetworkService.java:56) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.TcpTransport.(TcpTransport.java:153) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.newPluginService(TransportClient.java:103) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.buildTemplate(TransportClient.java:133) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.client.transport.TransportClient.(TransportClient.java:283) ~[elasticsearch-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.client.PreBuiltTransportClient.(PreBuiltTransportClient.java:128) ~[transport-6.4.3.jar:6.4.3]
	at org.elasticsearch.transport.client.PreBuiltTransportClient.(PreBuiltTransportClient.java:114) ~[transport-6.4.3.jar:6.4.3]

从内容稍加分析可以得知,代码里的ES版本咋是6.4.3.而我是7.3.2..why?其实从 MAVEN引用层级可以看出spring-boot-starter-data-elasticsearch2.2.5依赖了spring-data-elasticsearch 3.1.3-->再依赖了elasticsearch相关6.4.3的版本。那为什么提示 java.lang.NoSuchFieldError: LUCENE_6_0_0,这是我一开始提到的,es依赖了6.0的lucene.

记一次elasticSearch7.3.x+springboot配置+排错过程_第1张图片

因为目前到我写文章的时间

spring-boot-starter-data-elasticsearch最高版本是2.2.5 ,那就不引用它了。直接引用elasticsearch依赖的组件就行了。

有些人问为什么不引用最新的spring-boot-data-elasticsearch (当前是3.2.5),因为还不够新,3.2.5依赖的是es6.8.5,

有些人还专门作了对照图,倒不如放弃依赖spring-boot-data-elasticsearch 。直接引用官方

如图:

        
        
            org.elasticsearch.client
            transport
             7.3.2
        
        
            org.elasticsearch
            elasticsearch
             7.3.2
        
        
            org.elasticsearch.client
            elasticsearch-rest-client
             7.3.2
        
        
            org.elasticsearch.client
            elasticsearch-rest-high-level-client
             7.3.2
        

这次编译,通过!

编译通过不代表可以顺利运行,执行查询方法bookService.findAll();怎么又报错?

Caused by: java.lang.NoSuchMethodError: org.elasticsearch.search.SearchHits.getTotalHits()J
	at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.doCount(ElasticsearchTemplate.java:513) ~[spring-data-elasticsearch-3.2.5.RELEASE.jar:3.2.5.RELEASE]
	at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.count(ElasticsearchTemplate.java:490) ~[spring-data-elasticsearch-3.2.5.RELEASE.jar:3.2.5.RELEASE]

package org.elasticsearch.search;
.....

    @Nullable
    public TotalHits getTotalHits() {
        return this.totalHits;
    }

咱们查看代码很容易看出es 的getTotalHits返回的类型为TotalHits,而spring-data-elasticsearch3.1.5返回类型却为long。明显是spring-data的代码版本没更新引用的代码错误。

尝试更新到最新的spring-data-elasticsearch 3.2.5,仍然是未对totalhits作处理。怎么办呢?看来截止发文(20-3-9)是无法使用es7.X.X版本了,不然得对spring-data-elasticsearch 作更改,当然不是不行,而是代价太大(比如可以用aspectj对报错方法进行拦截),最简单的只能是降低ES的版块(目前3.2.5支持的elasticsearch最高版本为6.8.6,将es版本换下来,即可正常运行。也可不使用spring-data-elasticsearch,直接直接elasticsearchTemplate调用)。

 

你可能感兴趣的:(疑惑排障)