相关文章推荐
路过的帽子  ·  .Net ...·  2 周前    · 
正直的火车  ·  Visual C++ 中的云和 Web ...·  1 周前    · 
呐喊的木耳  ·  干货 · ...·  3 月前    · 
酷酷的开心果  ·  c++ - How do you ...·  1 年前    · 

上一篇中我们讲到ElasticSearch中分为五类API(查看API,文档API,搜索API,索引API,集群API),这篇我们继续研究cat API中的重要编码结构。

RestController的继承关系

从Node实例化的过程中,我们知道ActionModule是Node提供Rest请求功能的主要模块。RestController的实例是在ActionModule实例化的时候传入的重要参数之一,RestController是API提供服务的关键类之一,我们先从这个类开始梳理Rest API的加载逻辑。

RestController的继承关系

RestController继承自AbstractComponent,实现了HttpServerTransport.Dispatcher接口。

抽象类AbstractComponent,没什么复杂的逻辑,就是定义了一个基类Logger,一个Deprecation的Logger,Deprecation的Logger用处是打印settings配置中不提倡的参数设定(提醒ElasticSearch的使用者),该抽象类只有两个关于日志的方法:

  • 调用AbstractComponent的logDeprecatedSetting(String settingName, String alternativeName)方法就能提示启动ElasticSearch的用户参数中的 settingName 是弃用的,可以用方法中的参数 alternativeName 来代替。
  • 调用AbstractComponent的logRemovedSetting(String settingName, String alternativeName)方法能提示用户 settingName 参数已经被移除,可用 alternativeName 来代替。
  • 因为设计思路是将 dispatchRequest 这样的方法设计成接口,而发送请求逻辑分组率属于HttpServerTransport,所以将Dispatcher接口设计成HttpServerTransport的内部接口,这样所有的Dispatcher的实现类都会带有HttpServerTransport接口的标记。

    HttpServerTransport接口又实现了LifecycleComponent接口,LifecycleComponent接口标记了生命周期状态相关的逻辑,如下图:

    LifecycleComponent中的抽象方法

    其中Releasable类是ElasticSearch自己封装JDK1.7中的AutoCloseable。从LifecycleComponent的方法中可以看出该接口主要标记了Component的生命周期状态相关,当然还有添加和移除生命周期监听器,主要还是看LifecycleComponent的实现类是怎么实现这些标记的逻辑的。

    下面我们查看HttpServerTransport接口的逻辑,这个接口也不复杂,在HttpServerTransport接口中则主要配置了http线程的线程名前缀,绑定的Address,Http信息和状态。

    在HttpServerTransport的内部接口Dispatcher中,主要是两个方法:

  • void dispatchRequest(RestRequest request, RestChannel channel, ThreadContext threadContext),发送 request 到相关处理请求程序,如果request不能被任何处理请求程序处理则直接响应给 RestChannel
  • void dispatchBadRequest(RestRequest request, RestChannel channel, ThreadContext threadContext, Throwable cause),发送一个失败的 RestRequest ,用在request是残缺的情况下。
  • RestController中的主要方法

    梳理了RestController的父类结构,终于到了梳理RestController本身的时候了。RestController中最关键的方法是:

  • dispatchRequest(RestRequest request, RestChannel channel, ThreadContext threadContext)
  • registerHandler(RestRequest.Method method, String path, RestHandler handler)
  • registerHadler方法

    RestController的registerHandler方法做了哪些事呢?registerHandler的主要功能是当注册了一个REST处理程序后,如果提供的方法和路径之一匹配请求时,执行处理程序。

    查看源码我们会发现主要做了两个操作

  • registerHandler方法将 BaseRestHandler 的实例注册到 usageService 中,UsageService是监控ElasticSearch特性的服务(UsageService的主要逻辑是统计了RestController实例中的handler的占用数,底层是用的LongAdder,其适用于统计计数的场景),简而言之就是让Node的usageService加入对参数中handler和path的监控。
  • 更新handlers中的参数。因为RestController中持有一个PathTrie<MethodHandlers>类型的handler,每次注册都更新这个handler里面的值。
  • dispatchRequest方法

    这个方法是实现了Dispatcher接口中的dispatchRequest方法。

    由于ElasticSearch没有用到任何WEB框架,rest请求底层都是使用Netty实现的,收到的请求都是从ElasticSearch的transport-netty4模块里面发送给ElasticSearch的核心的。

  • transport-netty4模块的Netty4HttpRequestHandler类的channelRead0(ChannelHandlerContext ctx, Object msg)方法接受到其请求,然后发送给Netty4HttpServerTransport的dispathchRequest方法
  • Netty4HttpServerTransport再转发给RestController的DispatchRequest方法
  • RestController中dispatchRequest,遍历所有可能的处理程序,发送请求:

        Iterator<MethodHandlers> allHandlers = getAllHandlers(request);
        for (Iterator<MethodHandlers> it = allHandlers; it.hasNext(); ) {
            final Optional<RestHandler> mHandler = Optional.ofNullable(it.next()).flatMap(mh -> mh.getHandler(request.method()));
            requestHandled = dispatchRequest(request, channel, client, mHandler);
            if (requestHandled) {
                break;
    

    如果返回的requestHandled为false,则返回失败的handleBadRequest(request, channel);

    CAT API

    cat aliases API

    aliases显示有关当前配置的别名的信息,包括过滤器和路由信息。

    GET /_cat/aliases?v
    

    可能的响应:

    alias  index filter routing.index routing.search
    alias1 test1 -      -            -
    alias2 test1 *      -            -
    alias3 test1 -      1            1
    alias4 test1 -      2            1,2
    

    输出显示alias2已经配置了一个过滤器,以及alias3alias4中的特定路由配置。

    如果只想获取有关特定别名的信息,则可以使用逗号分隔格式指定别名作为URL参数,例如,/_cat/aliases/aliases/alias1,alias2

    REST请求是通过准备一个channel消费者(RestChannelConsumer)来处理的,Node在接收到aliases catAPI请求后,转发到RestAliasAction的doCatRequest方法,该方法会先确定这个请求是否是来自本地。RestAliasAction类的doCatRequest方法会返回一个RestChannelConsumer。

    RestAliasAction类的doCatRequest方法接收两个参数RestRequest和NodeClient。