java搜索框设计,基于Java、Kafka、ElasticSearch的搜索框架的设计与实现

Jkes

Jkes是一个基于Java、Kafka、ElasticSearch的搜索框架。Jkes提供了注解驱动的JPA风格的对象/文档映射,使用rest api用于文档搜索。

安装

可以参考jkes-integration-test项目快速掌握jkes框架的使用方法。jkes-integration-test是我们用来测试功能完整性的一个Spring Boot Application。

安装jkes-index-connector和jkes-delete-connector到Kafka Connect类路径

安装 Smart Chinese Analysis Plugin

sudo bin/elasticsearch-plugin install analysis-smartcn

配置引入jkes-spring-data-jpa依赖

添加配置

b65b1fb9be8f5e112329751c7406f9fe.png

提供JkesProperties Bean

6d2ca6c4336ba77f25b03861a094286d.png

这里可以很灵活,如果使用Spring Boot,可以使用@ConfigurationProperties提供配置

增加索引管理端点 因为我们不知道客户端使用的哪种web技术,所以索引端点需要在客户端添加。比如在Spring MVC中,可以按照如下方式添加索引端点

cef7be7ee0a6b3c29bfb626d5cfd6ed7.png

快速开始

索引API

使用com.timeyang.jkes.core.annotation包下相关注解标记实体

b1b8f61bd6c814c62781ce79b6ae4682.png

b1486214bbb29f93ed5ed02b1454cf6f.png

当更新实体时,文档会被自动索引到ElasticSearch;删除实体时,文档会自动从ElasticSearch删除。

搜索API

启动搜索服务jkes-search-service,搜索服务是一个Spring Boot Application,提供rest搜索api,默认运行在9000端口。

URI query

curl -XPOST localhost:9000/api/v1/integration_test_person_group/person_group/_search?from=3&size=10

Nested query

integration_test_person_group/person_group/_search?from=0&size=10

{

"query": {

"nested": {

"path": "persons",

"score_mode": "avg",

"query": {

"bool": {

"must": [

{

"range": {

"persons.age": {

"gt": 5

}

}

}

]

}

}

}

}

}

match query

integration_test_person_group/person_group/_search?from=0&size=10

{

"query": {

"match": {

"interests": "Hadoop"

}

}

}

bool query

a38ade2ffe45c1614fda31ef6b3d7f51.png

Source filtering

integration_test_person_group/person_group/_search

{

"_source": false,

"query" : {

"match" : { "name" : "name17" }

}

}

integration_test_person_group/person_group/_search

{

"_source": {

"includes": [ "name", "persons.*" ],

"excludes": [ "date*", "version", "persons.age" ]

},

"query" : {

"match" : { "name" : "name17" }

}

}

prefix

integration_test_person_group/person_group/_search

{

"query": {

"prefix" : { "name" : "name" }

}

}

wildcard

integration_test_person_group/person_group/_search

{

"query": {

"wildcard" : { "name" : "name*" }

}

}

regexp

integration_test_person_group/person_group/_search

{

"query": {

"regexp":{

"name": "na.*17"

}

}

}

Jkes工作原理

索引工作原理:

应用启动时,Jkes扫描所有标注@Document注解的实体,为它们构建元数据。

基于构建的元数据,创建index和mappingJson格式的配置,然后通过ElasticSearch Java Rest Client将创建/更新index配置。

为每个文档创建/更新Kafka ElasticSearch Connector,用于创建/更新文档

为整个项目启动/更新Jkes Deleter Connector,用于删除文档

拦截数据操作方法。将* save(*)方法返回的数据包装为SaveEvent保存到EventContainer;使用(* delete*(..)方法的参数,生成一个DeleteEvent/DeleteAllEvent保存到EventContainer。

拦截事务。在事务提交后使用JkesKafkaProducer发送SaveEvent中的实体到Kafka,Kafka会使用我们提供的JkesJsonSerializer序列化指定的数据,然后发送到Kafka。

与SaveEvent不同,DeleteEvent会直接被序列化,然后发送到Kafka,而不是只发送一份数据

与SaveEvent和DeleteEvent不同,DeleteAllEvent不会发送数据到Kafka,而是直接通过ElasticSearch Java Rest Client删除相应的index,然后重建该索引,重启Kafka ElasticSearch Connector

查询工作原理:

查询服务通过rest api提供

我们没有直接使用ElasticSearch进行查询,因为我们需要在后续版本使用机器学习进行搜索排序,而直接与ElasticSearch进行耦合,会增加搜索排序API的接入难度

查询服务是一个Spring Boot Application,使用docker打包为镜像

查询服务提供多版本API,用于API进化和兼容

查询服务解析json请求,进行一些预处理后,使用ElasticSearch Java Rest Client转发到ElasticSearch,将得到的响应进行解析,进一步处理后返回到客户端。

为了便于客户端人员开发,查询服务提供了一个查询UI界面,开发人员可以在这个页面得到预期结果后再把json请求体复制到程序中。

At-Least Once Delivery :

Jkes使用每个关系表的每条记录的更新时间戳进行来实现最少一次索引。jkes会定期checkpoint每个表的索引时间戳位置,在failure recovery时,从该时间戳开始拉取每个表的最新数据,索引到数据库,使用ElasticSearch的版本机制确保旧的数据不会覆盖新的索引。

checkpoint数据仅用于failure recovery。正常情况下,jkes是在数据库事务完成后发布更新和我删除事件到kafka。只有出现失败,导致事务完成后,数据还没有发布到kafka,这种情况下jkes才会在failure recovery时使用checkpoint数据重新索引。数据删除的最少一次交付目前需要在数据库中记录一张删除事件表,用于在failure recovery时发布删除事件,该功能性能较差,目前尚未实现。

如果当前没有checkpoint元数据,则会全量索引每个表。流程图

7e00e087f6080e06b5e61bbd5deea271.png

模块介绍

jkes-core

jkes-core是整个jkes的核心部分。主要包括以下功能:

annotation包提供了jkes的核心注解

elasticsearch包封装了elasticsearch相关的操作,如为所有的文档创建/更新索引,更新mapping

kafka包提供了Kafka 生产者,Kafka Json Serializer,Kafka Connect Client

metadata包提供了核心的注解元数据的构建与结构化模型

event包提供了事件模型与容器

exception包提供了常见的Jkes异常

http包基于Apache Http Client封装了常见的http json请求

support包暴露了Jkes核心配置支持

util包提供了一些工具类,便于开发。如:Asserts, ClassUtils, DocumentUtils, IOUtils, JsonUtils, ReflectionUtils, StringUtils

jkes-boot

jkes-boot用于与一些第三方开源框架进行集成。

当前,我们通过jkes-spring-data-jpa,提供了与spring data jpa的集成。通过使用Spring的AOP机制,对Repository方法进行拦截,生成SaveEvent/DeleteEvent/DeleteAllEvent保存到EventContainer。通过使用我们提供的SearchPlatformTransactionManager,对常用的事务管理器(如JpaTransactionManager)进行包装,提供事务拦截功能。

在后续版本,我们会提供与更多框架的集成。

jkes-spring-data-jpa说明:

ContextSupport类用于从bean工厂获取Repository Bean

@EnableJkes让客户端能够轻松开启Jkes的功能,提供了与Spring一致的配置模型

EventSupport处理事件的细节,在保存和删除数据时生成相应事件存放到EventContainer,在事务提交和回滚时处理相应的事件

SearchPlatformTransactionManager包装了客户端的事务管理器,在事务提交和回滚时加入了回调hook

audit包提供了一个简单的AuditedEntity父类,方便添加审计功能,版本信息可用于结合ElasticSearch的版本机制保证不会索引过期文档数据

exception包封装了常见异常

intercept包提供了AOP切点和切面

index包提供了全量索引功能。当前,我们提供了基于线程池的索引机制和基于ForkJoin的索引机制。在后续版本,我们会重构代码,增加基于阻塞队列的生产者-消费者模式,提供并发性能

jkes-services

jkes-services主要用来提供一些服务。 目前,jkes-services提供了以下服务:

jkes-delete-connector

jkes-delete-connector是一个Kafka Connector,用于从kafka集群获取索引删除事件(DeleteEvent),然后使用Jest Client删除ElasticSearch中相应的文档。

借助于Kafka Connect的rest admin api,我们轻松地实现了多租户平台上的文档删除功能。只要为每个项目启动一个jkes-delete-connector,就可以自动处理该项目的文档删除工作。避免了每启动一个新的项目,我们都得手动启动一个Kafka Consumer来处理该项目的文档删除工作。尽管可以通过正则订阅来减少这样的工作,但是还是非常不灵活

jkes-search-service

jkes-search-service是一个restful的搜索服务,提供了多版本的rest query api。查询服务提供多版本API,用于API进化和兼容

jkes-search-service目前支持URI风格的搜索和JSON请求体风格的搜索。

我们没有直接使用ElasticSearch进行查询,因为我们需要在后续版本使用机器学习进行搜索排序,而直接与ElasticSearch进行耦合,会增加搜索排序的接入难度

查询服务是一个Spring Boot Application,使用docker打包为镜像

查询服务解析json请求,进行一些预处理后,使用ElasticSearch Java Rest Client转发到ElasticSearch,将得到的响应进行解析,进一步处理后返回到客户端。

为了便于客户端人员开发,查询服务提供了一个查询UI界面,开发人员可以在这个页面得到预期结果后再把json请求体复制到程序中。

后续,我们将会基于zookeeper构建索引集群,提供集群索引管理功能

jkes-integration-test

jkes-integration-test是一个基于Spring Boot集成测试项目,用于进行功能测试。同时测量一些常见操作的吞吐率

Development

To build a development version you'll need a recent version of Kafka. You can build jkes with Maven using the standard lifecycle phases.

最后

如果你对技术提升很感兴趣,可以加入我的Java进阶架构来交流学习:805--685--193,里面都是同行,有资源共享。欢迎1到5年的工程师加入,合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

d24bc8530bb157b6d0e5124dffd6cc6f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值