ES源码学习之,得到API的实现逻辑

  

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(),新的BaseTransportResponseHandler

ES源码学习之,得到API的实现逻辑