ES源码学习之--Get API的实现逻辑
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,Github上es项目讲述其易用性时,用来举例说明ES开箱即用的特性,用的就是Get API。片段摘取如下:-- 添加文档curl -XPUT 'http://localhost:9200/twitt
千家信息网最后更新 2026年11月03日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安全错误
数据库的锁怎样保障安全
互联网科技
哈尔滨大商圈互联网科技有限公司
新华互联网科技学校
互联网的科技
互联网科技有限公司经营范围
河南真二互联网科技有限公司
狮子座互联网科技
致骋互联网科技
有木互联网科技
郑州华宇互联网科技
济南华为互联网科技产业总部基地
互联网企业和科技型企业
互联网科技革命什么开始
深圳市罗太互联网科技有限公司
高科技互联网发展前景如何
互联网硬科技公司
福建互联网展示科技馆设计
容联科技互联网电商
深圳互联网科技园地址
瑞安市蟠桃会互联网科技有限公司
互联网科技垄断
亿策互联网科技
互联网科技小额贷款
盛创互联网科技有限公司
互联网汽车科技小镇
厦门比较好的科技互联网公司
中和天地互联网科技有限公司
互联网科技包装股份有限公司上市
互联网科技接地气
互联网企业和网络科技有限公司