从 Node 实例化的过程中,我们知道 ActionModule 是 Node 提供 Rest 请求功能的主要模块。RestController 的实例是在 ActionModule 实例化的时候传入的重要参数之一,RestController 是 API 提供服务的关键类之一,我们先从这个类开始梳理 Rest API 的加载逻辑。
RestController 的继承关系
RestController 继承自 AbstractComponent,实现了 HttpServerTransport.Dispatcher 接口。
抽象类 AbstractComponent,没什么复杂的逻辑,就是定义了一个基类 Logger,一个 Deprecation 的 Logger,Deprecation 的 Logger 用处是打印 settings 配置中不提倡的参数设定(提醒 ElasticSearch 的使用者),该抽象类只有两个关于日志的方法:
因为设计思路是将 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 中,主要是两个方法:
梳理了 RestController 的父类结构,终于到了梳理 RestController 本身的时候了。RestController 中最关键的方法是:
RestController 的 registerHandler 方法做了哪些事呢?registerHandler 的主要功能是当注册了一个 REST 处理程序后,如果提供的方法和路径之一匹配请求时,执行处理程序。
查看源码我们会发现主要做了两个操作
这个方法是实现了 Dispatcher 接口中的 dispatchRequest 方法。
由于 ElasticSearch 没有用到任何 web 框架,rest 请求底层都是使用 Netty 实现的,收到的请求都是从 ElasticSearch 的 transport-netty4 模块里面发送给 ElasticSearch 的核心的。
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);
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 已经配置了一个过滤器,以及 alias3 和 alias4 中的特定路由配置。
如果只想获取有关特定别名的信息,则可以使用逗号分隔格式指定别名作为 URL 参数,例如,/_cat/aliases/aliases/alias1,alias2
REST 请求是通过准备一个 channel 消费者(RestChannelConsumer)来处理的,Node 在接收到 aliases catAPI 请求后,转发到 RestAliasAction 的 doCatRequest 方法,该方法会先确定这个请求是否是来自本地。RestAliasAction 类的 doCatRequest 方法会返回一个 RestChannelConsumer。
RestAliasAction 类的 doCatRequest 方法接收两个参数 RestRequest 和 NodeClient。
doCatRequest 方法
这里的 NodeClient 是在本地节点上执行操作的 Client。继承关系如下图:
NodeClient 的继承关系
其中 Client 接口提供了一个用于对集群执行 actions 或操作的接口。客户可以从一个 org.elasticsearch.node.node 检索开始,或远程连接使用一个或多个节点 org.elasticsearch.client.transport.transportclient。
而 NodeClient 的 admin 方法是取得 AbstractClient.Admin.IndicesAdmin 实例,通过参数 "索引别名请求 (getAliasesRequest)" 和 " 通知结果监听器 (new RestResponseListener
来源: http://www.jianshu.com/p/0b6fbee53968