Github上es项目讲述其易用性时,用来举例说明es开箱即用的特性,用的就是API。片段摘取如下:
<代码>——添加文档 旋度-XPUT”http://localhost: 9200/微博/doc/1 ?application/json漂亮' - h - type:“- d” { “用户”:“kimchy”, “post_date”:“2009-11-15×××3:12:00”, “消息”:“尝试Elasticsearch,到目前为止,好吗?” }' ——读取文档 curl xget”http://localhost: 9200/微博/doc/1 ?漂亮=true”代码>
Get API通常的用途有2点:
1检测添加的文档跟预期是否相符,这在问题排查时超级实用。
2根据id获取整个文档明细,用于搜索的获取阶段。
研究ES的内部机制,获得API是一个极佳的切入点。通过API,可以了解到的知识点有:
。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的插件时,其内部流程是很好的借鉴。内部细节了解越多,越不容易踩坑。
GET API的核心流程如下:
<代码> s1:接收客户端请求代码>
<代码>看到controller.registerHandler()方法,很容易就联想到http的请求 公开课RestGetAction延伸BaseRestHandler { @ inject 公共RestGetAction(设置设置,RestController控制器,客户端){ 超级(设置、控制器、客户); 控制器。registerHandler(获得“/{指数}/{类型}/{id}”,这一点); } @Override 公共空间handleRequest(最终RestRequest请求,最终RestChannel通道,最终客户端){ … 客户端。get (getRequest,新的RestBuilderListener(频道){ … }); } } 代码> >之前 <代码> s2:在当前节点执行该请求代码>
<代码>公共类NodeClient延伸AbstractClient { … @Override 公共& lt;请求ActionRequest延伸,响应ActionResponse延伸, RequestBuilder延伸ActionRequestBuilder<请求、响应RequestBuilder>比; 空白doExecute (Action<请求、响应RequestBuilder>行动,请求请求,ActionListener侦听器){ Response> TransportAction<请求;transportAction=actions.get(行动); … transportAction。执行(请求,侦听器); } } 这里隐含了一个行动的映射表,如下: 公开课ActionModule延伸AbstractModule { … @Override 保护无效配置(){ … 获取registerAction (GetAction。例如,TransportGetAction.class); … } } 代码> >之前 <代码> s3:定位文档所在分片代码>
<代码>文档的定位思路很简单,默认根据文档id,用哈希函数计算出文档的分片ShardId,通过分片ShardId定位出NodeId。 ES内部维护了一张类似路由表的对象,类名就是RoutingTable。通过RoutingTable,可以根据索引名称找到所有的分片;可以通过分片Id找到分片对应的集群节点。 关于文档的定位,从应用的角度有两个知识点:路由和偏好 公共类TransportGetAction TransportSingleShardAction<延伸;GetRequest GetResponse>{ … @Override 保护ShardIterator碎片(ClusterState状态,InternalRequest请求){ 返回clusterService.operationRouting () request.concreteIndex .getShards (clusterService.state () (), request.request () .type (), request.request () .id (), request.request () .routing (), request.request () .preference ()); } }代码><代码> s4:将请求转发到分片所在的节点代码>
<代码>请求的分发,涉及到ES的RPC通信。上一步定位到NodeId,将请求发送到该NodeId即可。 由于西文的每个节点代码都是一样的,因此每个节点既承担服务器也承担客户机的责任,这跟其他的RPC框架有所不同。 核心方法是transportService.sendRequest()和messageReceived ()。 公共抽象类TransportSingleShardAction<请求SingleShardRequest延伸,响应ActionResponse>延伸;Response>延伸TransportAction<请求;{ 类AsyncSingleAction { 公共空间开始(){ transportService.sendRequest (clusterService.localNode ()、transportShardAction internalRequest.request(),新的BaseTransportResponseHandlerES源码学习之,得到API的实现逻辑