ES源码学习之--Get API的实现逻辑
发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,Github上es项目讲述其易用性时,用来举例说明ES开箱即用的特性,用的就是Get API。片段摘取如下:-- 添加文档curl -XPUT 'http://localhost:9200/twitt
千家信息网最后更新 2025年01月31日ES源码学习之--Get API的实现逻辑
Github上es项目讲述其易用性时,用来举例说明ES开箱即用的特性,用的就是Get API。片段摘取如下:
-- 添加文档curl -XPUT 'http://localhost:9200/twitter/doc/1?pretty' -H 'Content-Type: application/json' -d '{ "user": "kimchy", "post_date": "2009-11-15×××3:12:00", "message": "Trying out Elasticsearch, so far so good?"}'-- 读取文档curl -XGET 'http://localhost:9200/twitter/doc/1?pretty=true'
Get API通常的用途有2点:
1 检测添加的文档跟预期是否相符, 这在问题排查时超级实用。
2 根据id获取整个文档明细, 用于搜索的fetch阶段。
研究ES的内部机制, Get API是一个极佳的切入点。通过Get API, 可以了解到的知识点有:
a. ES的rest api实现方式。
b. ES的文档路由方式。
c. ES的RPC实现机制。
d. ES的translog.
e. ES如何使用lucene 的IndexSearcher。
f. ES如何根据id获取到lucene的doc_id
。
g. ES如何根据lucene的doc_id
获取文档明细。
.......
研究ES的内部机制,有助于释放ES的洪荒之力。例如:根据业务开发ES的plugin时,其内部流程是很好的借鉴。 内部细节了解越多,越不容易踩坑。
GET API的核心流程如下:
s1: 接收客户端请求
看到controller.registerHandler()方法,很容易就联想到http的请求public class RestGetAction extends BaseRestHandler { @Inject public RestGetAction(Settings settings, RestController controller, Client client) { super(settings, controller, client); controller.registerHandler(GET, "/{index}/{type}/{id}", this); } @Override public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { ... client.get(getRequest, new RestBuilderListener(channel) { ... }); }}
s2: 在当前节点执行该请求
public class NodeClient extends AbstractClient { ... @Override public > void doExecute(Action action, Request request, ActionListener listener) { TransportAction transportAction = actions.get(action); ... transportAction.execute(request, listener); }}这里隐含了一个actions的映射表, 如下:public class ActionModule extends AbstractModule { ... @Override protected void configure() { ... registerAction(GetAction.INSTANCE, TransportGetAction.class); ... }}
s3: 定位文档所在分片
文档的定位思路很简单, 默认根据文档id, 用hash函数计算出文档的分片ShardId, 通过分片ShardId定位出NodeId。 ES内部维护了一张类似路由表的对象,类名就是RoutingTable. 通过RoutingTable, 可以根据索引名称找到所有的分片;可以通过分片Id找到分片对应的集群Node. 关于文档的定位,从应用的角度有两个知识点:routing和preferencepublic class TransportGetAction extends TransportSingleShardAction { ... @Override protected ShardIterator shards(ClusterState state, InternalRequest request) { return clusterService.operationRouting() .getShards(clusterService.state(), request.concreteIndex(), request.request().type(), request.request().id(), request.request().routing(), request.request().preference()); }}
s4: 将请求转发到分片所在的节点
请求的分发,涉及到ES的RPC通信。上一步定位到NodeId, 将请求发送到该NodeId即可。由于ES的每个Node代码都是一样的, 因此每个Node既承担Server也承担Client的责任,这跟其他的RPC框架有所不同。核心方法是transportService.sendRequest() 和 messageReceived()。 public abstract class TransportSingleShardAction extends TransportAction { class AsyncSingleAction { public void start() { transportService.sendRequest(clusterService.localNode(), transportShardAction, internalRequest.request(), new BaseTransportResponseHandler() { ... }); } } private class ShardTransportHandler extends TransportRequestHandler { @Override public void messageReceived(final Request request, final TransportChannel channel) throws Exception { ... Response response = shardOperation(request, request.internalShardId); channel.sendResponse(response); } }}
s5: 通过id读取索引文件获取该id对应的文档信息
这里分两个阶段:step1: 将type和id合并成一个字段,从lucene的倒排索引中定位lucene的doc_idstep2: 根据doc_id从正向信息中获取明细。public final class ShardGetService extends AbstractIndexShardComponent { ... private GetResult innerGet(String type, String id, String[] gFields, boolean realtime, long version, VersionType versionType, FetchSourceContext fetchSourceContext, boolean ignoreErrorsOnGeneratedFields) { fetchSourceContext = normalizeFetchSourceContent(fetchSourceContext, gFields); ... get = indexShard.get(new Engine.Get(realtime, new Term(UidFieldMapper.NAME, Uid.createUidAsBytes(typeX, id))) .version(version).versionType(versionType)); ... innerGetLoadFromStoredFields(type, id, gFields, fetchSourceContext, get, docMapper, ignoreErrorsOnGeneratedFields); } }
(注: 如果是realtime=true, 则先从translog中读取source, 没有读取到才从索引中读取)
s5涉及到Lucene的内部实现, 这里不展开赘述。
最后总结一下:
Get API是ES内部打通了整个流程的功能点。从功能上看,它足够简单;从实现上看,他又串联了ES的主流程,以它为切入口,不会像展示You Know, for Search
的RestMainAction
那样浮于表面;又不会像实现搜索的接口那样庞杂难懂。
文档
定位
索引
明细
机制
流程
两个
信息
功能
就是
所在
方式
方法
核心
知识
知识点
节点
路由
阶段
搜索
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
黑客对抗网络安全官
广州三零一互联网科技贴吧
怎么看主机是不是服务器主板
浏览器和web服务器
怎么能把数据库卸载干净
怎样面临网络安全问题
上海寰企网络技术有限公司
新乡学院数据库原理及应用课程
游戏数据服务器
网络安全态势感知管理策略
网络安全管理实验南邮
长春市委网络安全信息工作
苏州c语言软件开发大概要多少钱
德州便民平台软件开发哪儿好
网络安全攻防一体机
网络安全低估
各数据库的检索情况
计算机网络技术常用的熟知端口
rss 服务器
河北学网络技术在哪
公安部网络安全保护条例
浙江网络技术服务客户至上
数据库安全技术分析论文
文华财经行情服务器
陆军网络安全展板
公务员网络安全管理是什么
苏州网络安全基地
ssr订阅服务器地址2021
虹口区国际网络技术服务常见问题
level3是哪个服务器