ES源码分析-关于action

  • ES源码版本 7.10java

启动过程当中的action

好比咱们有个搜索请求:web

curl -X GET "localhost:9200/blogs/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content""elasticsearch"
        }
      },
      "field_value_factor": {
        "field""likes",
        "factor"2,
        "modifier""sqrt",
        "missing"1
      }
    }
  }
}
'

这个请求ES是如何找到对应的模块去处理呢?答案是ES在启动过程当中注册了请求的URL和对应的Action的绑定关系。json

RestSearchAction.java
微信

好比上面,RestSearchAction就是对应/{index}/_search这个URL模板的处理Action,ES里有不少继承自BaseRestHandler的Action绑定到不一样的Action上。本篇就以/{index}/_search为例来讲明。数据结构

具体是怎么关联的呢?咱们继续分析。app

ES在启动的时候要初始化Node类。curl

Bootstrap.java
elasticsearch

在构造函数里会调用ActionModule类,这个类就是ES的Action管理的核心处理类,后面讲搜索过程当中的Action部分它也会出现。Node构造函数里会调用ActionModule类的initRestHandlers方法来注册。函数

ActionModule.java
url

initRestHandlers这个方法里会调用RestController的registerHandler方法完成注册。

RestController.java

handlers.insertOrUpdate方法内部就不深刻了,这里实际上是用了字典树的数据结构(Trie),存储path(/{index}/_search)和Handler的对应关系。Trie的核心思想是空间换时间,利用字符串的公共前缀来下降查询时间的开销以达到提升效率的目的。

因此在请求阶段查找的时候,也一样是根据url path去查找对应的handler。这部分在下个章节会提到。

还有一个TransportAction须要说明下。在ActionModule类的setupActions方法,会将Action和对应的TransportAction注册到actions对象中。这个Action指的是SearchAction(search场景下),以下图所示:

ActionModule.java

其实底层就是放在一个Map里创建一个映射关系。请求的时候去这个Map里找。

请求过程当中的action

了解了Action相关的启动加载流程,下面咱们来看一个查询的调用链路,顺藤摸瓜,看看一个查询请求是怎么应用到Action的。

首先全部的请求入口都是netty,准确来讲对外的请求都是基于netty4封装的HTTP server。而后server分发请求。这部分其实更多的是netty和http相关的通用逻辑,这里不作详细介绍了。HTTP server的分发逻辑最终会调用到RestController类的dispatchRequest方法

RestController.java

tryAllHandlers方法前面这个循环是用来把http请求的头部信息传递到ES底层调用,从而作一些特殊处理。header里的key是ES定义的,value咱们能够本身指定。好比X-Opaque-Id这个key,若是咱们应用端请求的时候赋值了,能够用来跟踪从http请求到底层我的任务的执行链路。

RestController.java

接着看,好比仍是上面那个搜索请求:

curl -X GET "localhost:9200/blogs/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content""elasticsearch"
        }
      },
      "field_value_factor": {
        "field""likes",
        "factor"2,
        "modifier""sqrt",
        "missing"1
      }
    }
  }
}
'

RestController.java

这段代码能够根据个人请求的path,这里是

/blogs/_search

找到对应

/{index}/_search

RestHandler,这个查找就是根据url path去Trie树查找。而后经过dispatchRequest方法分发给找到的Handler处理。这个方法会统一调用到BaseRestHandler这个基类进行处理

BaseRestHandler.java

根据前面的path(/{index}/_search),咱们知道上图中找到的这个action必然是RestSearchAction,而后根据这个类重载的prepareRequest方法能够找到accept的执行逻辑。

RestSearchAction.java

这里最终会调用NodeClient类找到action(注意这里的action和上面的action不是一个东西,这里的action是searchAction)对应的TransPortAction,前面在启动章节说过,在ActionModule中会将Action和对应的TransportAction注册到actions对象中。如今就是从actions对象(是个Map)中拿到对应的TransportAction,并并执行其execute()方法。

在NodeClient中会根据传入的Action参数从actions获取在ActionModule中注册的TransportAction,并执行其execute()方法

TransportAction后面的的逻辑,就是具体的ES查询逻辑处理了。这个后面会有专门的系列文章。这里再也不详述。

上面的调用链路,能够用一个时序图表示



本文分享自微信公众号 - 犀牛饲养员的技术笔记(coder_start_up)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索