ES源码学习之--Get API的实现逻辑
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,Github上es项目讲述其易用性时,用来举例说明ES开箱即用的特性,用的就是Get API。片段摘取如下:-- 添加文档curl -XPUT 'http://localhost:9200/twitt
千家信息网最后更新 2025年12月02日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安全错误
数据库的锁怎样保障安全
朔州市穿越网络技术有限公司
长安路网络安全
韶关学习网络安全薪资高就业快
用什么软件可以传游戏数据库
华为服务器工程师好学吗
网络安全谁建设
世纪云涿州互联网科技有限公司
每日科技互联网报
三级数据库填空题题库百度云
数据清单中的阅读是数据库的吗
惠普服务器无法开机
怎么建立空数据库文件夹
ice服务器被炸前什么样
国家查滴滴网络安全
使用网络时如何做好网络安全防范
数据库最新技术 2018
中关村互联网前沿科技
思科email服务器配置实验
网络安全自查和抽查报告
基于sfp的文件管理服务器
前端数据库SQL
星型结构 数据库
使用网络技术措施遵循原则
档案软件开发合同
普通人如何学习网络安全
服务器连接不上啥子原因
网络安全工作汇报搞
丽江网络安全执法
服务器后面的锁什么用途
巨果网络技术有限公司