springboot2.0+elasticsearch5.5+rabbitmq搭建搜索服务的坑

前一阵子准备为项目搭建一个简单的搜索服务,虽然业务数据库mongodb提供了文本搜索的支持,但是在大量文档需要通过关键词进行定位时,es明显更加适合去作为一个搜索引擎(虽然我们之前大部分使用到了ELK那套分析和可视化的特性)。Elasticsearch建立在Lucene之上并且支持极其快速的查询和丰富的查询语法,偶尔也可以作为一个轻量级的NoSQL。但是对复杂查询和聚合操作的能力并不是很强。

本篇不会提及如何搭建一个简单搜索服务,而是记录一下大约一周工作时间内遇见的几个坑。。

为什么选择elasticsearch 5.x?

新服务没有任何历史包袱,理论上应该用最新的6.x,然而spring-data-elasticsearch只支持到的5.x,时间紧也无法很好直接封装一层api,也是因为ELK那套东西之前版本混乱,无奈es从2.x直接到了5.x。查询一下5.x和2.x的差别,简单说就是磁盘空间-50%,索引时间-50%,查询性能+25%。

由于spring-data-elasticsearch必须升级到3.0.7,导致spring必须升级到2.x,也直接导致了后面踩到的坑。

docker安装es会默认安装x-path plugin

虽然spring-data支持es5.x,但是功能并不非常完善,因此如果安装了x-path插件,需要引入org.elasticsearch.client:x-pack-transport:5.5.0,版本必须和es版本一致,并且自己实现TransportClient,如下

@Component
public class ESconfig {
 @Bean
 public TransportClient transportClient() throws UnknownHostException {
  TransportClient client = new PreBuiltXPackTransportClient(Settings.builder()
    .put("cluster.name", "docker-cluster")
    .put("xpack.security.user", "elastic:changeme")
    .build())
    .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("0.0.0.0"), 9300));
  return client;
 }
}

这也是因为不想再到docker里去处理x-path这个插件而选择的一个比较快捷的解决方案,没必要的情况下,暂时也不用接触到es本身的一些东西。

mq会保存message的class信息导致deserialized失败

一直没有提到标题中的rabbitmq,因为只是单纯的用它作为一个消息队列,当数据发生变化时,将消息id丢入mq,由search服务这边的consumer去消费。

问题就是在消息丢入mq时,封装成了一个自己的Object, 导致使用rabbitTemplate.receiveAndConvert时失败,因为message会带着Object的package信息。无奈之下,consumer只能直接获取queue里的message bytes, 用ObjectMapper.readValue的方法将json形式转换成一个Object。

gradle配置可以使用-Dloader.main指定启动函数

正是因为引入了mq,所以search服务需要启动一个consumer,用的方法是另外实现一个不启动Web服务的Application,并且配置一个SimpleMessageListenerContainer和MessageListenerAdapter如下:

 @Bean
 SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
   MessageListenerAdapter listenerAdapter,
   MQconfig properties) {
  SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
  container.setConnectionFactory(connectionFactory);
  container.setQueueNames(properties.getQueueName());
  container.setMessageListener(listenerAdapter);

  return container;
 }

 @Bean
 MessageListenerAdapter listenerAdapter() {
  MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(itemConsumer,
    "consume");
  return listenerAdapter;
 }

问题在于gradle配置的时候,找了很久如何使得build出来的jar包可以指定-Dloader.main指定启动Application,解决方法如下:
在xxx.gradle文件里添加

bootJar {
 manifest {
  attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
 }
}

在springboot 1.5.9的项目里,需要指定启动Application,需要添加

springBoot{
 layout = "ZIP"
}

查看是否生效的办法是build以后 直接解压jar包,在xxx(项目名)/META-INFO/MANIFEST.MF里查看,如果

Main-Class: org.springframework.boot.loader.PropertiesLauncher

则正确,如果

Main-Class: org.springframework.boot.loader.JarLauncher

则依旧会启动文件里的Start-Class

es无法修改Index的mapping

由于只是单纯使用了es的文本检索功能,导致实际应用时有许多搜索结果不尽如人意的地方,比如搜索“桌子”, 无法搜索到 “电脑桌/办公桌”等xx桌内容,这样的情况还有很多。 因此加入了synonym dictionary,在需要分词的字段上不使用本身的ik_smart分词器,这样某些字段的mapping需要改为

 // analyzer是自己的分词器名字
 @Field(type = FieldType.Text, index = true, analyzer = "synonym")
 private String description;

由于es的mapping无法修改,只能通过手动创建一个新的mapping,再通过reIndex方法去backfill数据(es5.x自带了reIndex 的api)。网上有通过alias的方法,在某些修改场景下,不需要重新启动/部署应用就可以平滑的修改mapping,具体可以查询了解一下。

以上差不多搭建一个搜索服务踩到的一些坑,有几个消耗了大量时间和精力去解决,在此列出来希望希望有借鉴意义。之后搜索服务有优化的地方,还会继续慢慢更新,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot整合ElasticSearch的示例代码

    ElasticSearch作为基于Lucene的搜索服务器,既可以作为一个独立的服务部署,也可以签入Web应用中.SpringBoot作为Spring家族的全新框架,使得使用SpringBoot开发Spring应用变得非常简单.本文要介绍如何整合ElasticSearch与SpringBoot. 实体设计: 每一本书(Book)都属于一个分类(Classify),都有一个作者(Author). 生成这个三个实体类,并实现其get和set方法. SpringBoot配置修改: 1.修改pom.xm

  • Spring Boot集成ElasticSearch实现搜索引擎的示例

    Elastic Search是一个开源的,分布式,实时搜索和分析引擎.Spring Boot为Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置.Spring Boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'StarterPOM'. ElasticSearch作为搜索引擎,我们需要解决2大问题: 1,  如何将被搜索的数据在ES上创建反向索引 2,  Java代码如何与E

  • Spring Boot整合Elasticsearch实现全文搜索引擎案例解析

    简单说,ElasticSearch(简称 ES)是搜索引擎,是结构化数据的分布式搜索引擎.Elastic Search是一个开源的,分布式,实时搜索和分析引擎.Spring Boot为Elasticsearch及Spring Data Elasticsearch提供的基于它的抽象提供了基本的配置.Spring Boot提供了一个用于聚集依赖的spring-boot-starter-data-elasticsearch 'StarterPOM'. 引入spring-boot-starter-dat

  • 详解spring-boot集成elasticsearch及其简单应用

    介绍 记录将elasticsearch集成到spring boot的过程,以及一些简单的应用和helper类使用. 接入方式 使用spring-boot中的spring-data-elasticsearch,可以使用两种内置客户端接入 1.节点客户端(node client): 配置文件中设置为local:false,节点客户端以无数据节点(node-master或node-client)身份加入集群,换言之,它自己不存储任何数据,但是它知道数据在集群中的具体位置,并且能够直接转发请求到对应的节

  • Spring boot中使用ElasticSearch的方法详解

    0.版本选择 我这里选择了5.6.x,记得如果spring-boot-starter-parent是1.x可以选择2.x版本的elasticsearch,版本要对应,不然会有莫名其妙的问题 1.安装ElasticSearch https://www.elastic.co/downloads/past-releases windows 测试的,解压就能用 解压,到bin目录,双击elasticsearch.bat 1.1安装elasticsearch-head https://github.com

  • Spring Boot整合ElasticSearch实现多版本兼容的方法详解

    前言 在上一篇学习SpringBoot中,整合了Mybatis.Druid和PageHelper并实现了多数据源的操作.本篇主要是介绍和使用目前最火的搜索引擎ElastiSearch,并和SpringBoot进行结合使用. ElasticSearch介绍 ElasticSearch是一个基于Lucene的搜索服务器,其实就是对Lucene进行封装,提供了 REST API 的操作接口 ElasticSearch作为一个高度可拓展的开源全文搜索和分析引擎,可用于快速地对大数据进行存储,搜索和分析.

  • Spring Boot与Kotlin 整合全文搜索引擎Elasticsearch的示例代码

    Elasticsearch 在全文搜索里面基本是无敌的,在大数据里面也很有建树,完全可以当nosql(本来也是nosql)使用. 这篇文章简单介绍Spring Boot使用Kotlin语言连接操作 Elasticsearch.但是不会做很详细的介绍,如果要深入了解Elasticsearch在Java/kotlin中的使用,请参考我之前编写的<Elasticsearch Java API 手册> https://gitee.com/quanke/elasticsearch-java/ 里面包含使

  • SpringBoot整合Elasticsearch并实现CRUD操作

     配置准备 在build.gradle文件中添加如下依赖: compile "org.elasticsearch.client:transport:5.5.2" compile "org.elasticsearch:elasticsearch:5.5.2" //es 5.x的内部使用的 apache log4日志 compile "org.apache.logging.log4j:log4j-core:2.7" compile "org

  • SpringBoot整合ElasticSearch实践

    本节我们基于一个发表文章的案例来说明SpringBoot如何elasticsearch集成.elasticsearch本身可以是一个独立的服务,也可以嵌入我们的web应用中,在本案例中,我们讲解如何将elasticsearch嵌入我们的应用中. 案例背景:每个文章(Article)都要属于一个教程(Tutorial),而且每个文章都要有一个作者(Author). 一.实体设计: Tutorial.java public class Tutorial implements Serializable

  • springboot2.0+elasticsearch5.5+rabbitmq搭建搜索服务的坑

    前一阵子准备为项目搭建一个简单的搜索服务,虽然业务数据库mongodb提供了文本搜索的支持,但是在大量文档需要通过关键词进行定位时,es明显更加适合去作为一个搜索引擎(虽然我们之前大部分使用到了ELK那套分析和可视化的特性).Elasticsearch建立在Lucene之上并且支持极其快速的查询和丰富的查询语法,偶尔也可以作为一个轻量级的NoSQL.但是对复杂查询和聚合操作的能力并不是很强. 本篇不会提及如何搭建一个简单搜索服务,而是记录一下大约一周工作时间内遇见的几个坑.. 为什么选择elas

  • SpringBoot2.0 整合 Dubbo框架实现RPC服务远程调用方法

    一.Dubbo框架简介 1.框架依赖 图例说明: 1)图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层或模块,蓝色的表示与业务有交互,绿色的表示只对 Dubbo 内部交互. 2)图中背景方块 Consumer, Provider, Registry, Monitor 代表部署逻辑拓扑节点. 3)图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用. 4)图中只包含 RPC

  • SpringBoot2.0集成WebSocket实现后台向前端推送信息

    什么是WebSocket? WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信--允许服务器主动发送信息给客户端. 为什么需要 WebSocket? 初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处? 答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息. 举例来说,我们想要查询当前的排队情况,只能是

  • 详解SpringBoot2.0的@Cacheable(Redis)缓存失效时间解决方案

    问题   @Cacheable注解不支持配置过期时间,所有需要通过配置CacheManneg来配置默认的过期时间和针对每个类或者是方法进行缓存失效时间配置. 解决   可以采用如下的配置信息来解决的设置失效时间问题 配置信息 @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { return new RedisCacheManager( RedisCacheWriter.no

  • springboot2.0集成rabbitmq的示例代码

    安装rabbitmq 简介: rabbitmq即一个消息队列,主要用来实现应用程序的异步和解耦,消息缓冲,消息分发的作用. 由于rabbitmq依赖于erlang语言,所以先安装erlang: 添加erlang solutions源 $ wget https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm $ sudo rpm -Uvh erlang-solutions-1.0-1.noarch.rpm $ su

  • SpringBoot2.0集成MQTT消息推送功能实现

    这几天在弄后端管理系统向指定的Android客户端推送消息的功能模块,查阅了网上很多博客介绍的许多方式,最终选择基于MQTT协议来实现,MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案. 实现MQTT协议的中间件有很多,我用的是Apollo服务器,如何搭建MQTT服务器,请查阅其他资料.这里,主要介绍SpringBoot2.0集成MQTT实现消息推送的功能.好,正式开始: 本文采用Gateway绑定的方式,网上也有介绍但不全面,还有其他采用Paho

  • shell 脚本自动搭建nfs服务的方法示例

    本文介绍了shell 脚本自动搭建nfs服务的方法示例,分享给大家,具体如下: #vim /sh/zidong_dajian_nfs_fuwu.sh #!/bin/bash #name:zidong_dajian_nfs_fuwu.sh #path:/sh/ #update:2017-9-17 #测试网络是否通畅 ping -c 1 172.16.13.254 >/dev/null && echo **********网络ok********** #第一步:关闭selinux和防火墙

  • java使用xfire搭建webservice服务的过程详解

    前言 以前用的都是 apache 的cxf来搞webservice,今天做项目发现这个项目用的是 xfire,于是搭一个,写个demo用一下,在此记录一下过程. 搭建过程 本文使用的是maven形式的web工程.不知道如何搭建web工程的看上一篇博文. 引入xfire的依赖 <dependency> <groupId>org.codehaus.xfire</groupId> <artifactId>xfire-all</artifactId> &

  • SpringBoot2.0+阿里巴巴Sentinel动态限流实战(附源码)

    Sentinel 是什么? 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性. Sentinel 具有以下特征: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围).消息削峰填谷.集群流量控制.实时熔断下游不可用应用等. 完备的实时监控:Sentinel 同时提供实时的监控功能.您可以在控制台中看到接入应用的

  • SpringBoot2.0 中 HikariCP 数据库连接池原理解析

    作为后台服务开发,在日常工作中我们天天都在跟数据库打交道,一直在进行各种CRUD操作,都会使用到数据库连接池.按照发展历程,业界知名的数据库连接池有以下几种:c3p0.DBCP.Tomcat JDBC Connection Pool.Druid 等,不过最近最火的是 HiKariCP. HiKariCP 号称是业界跑得最快的数据库连接池,自从 SpringBoot 2.0 将其作为默认数据库连接池后,其发展势头锐不可当.那它为什么那么快呢?今天咱们就重点聊聊其中的原因. 一.什么是数据库连接池

随机推荐