关于API调用链路,我们先从熟悉的MVC三层架构说起。做开发的比较熟悉spring springMVC ,我们熟悉的套路是,请求先到 controller层,然后controller去调用service层,然后结果返回。通常,我们还有tomcat作为服务器,来接收请求,接收到的请求调用controller层。用户的请求,例如http请求,一般是先到tomcat服务,然后调用程序的controller。 然后再看es是怎么玩的,es没有用spring spingMVC这些,只用了Guice来做容器管理,es并没有选择使用类似于tomcat的服务器来接收请求,而是选择netty来实现服务器,完成请求的接收与发送。这就对应了下图的RestController,这一层这是和tomcat有相同的作用。而下图的BaseRestHandler实际上可以理解成来选择controller路由器,它要根据请求中的url路径,来选择一个controller。而下图第三步的RestSearchAction,正是我们之前理解的MVC中的 controller层,不同的功能放在了不同的RestAction里边,实际上一些逻辑也放在这里边。而NodeClient这一层实际上有点service的味道,它是真正去执行逻辑的地方。和传统的服务不同的是,es是一个天然的分布式应用。
-
Netty4HttpServerTransport.dispatchRequest()
-
RestController.dispatchRequest().tryAllHandlers()
-
RestController.dispatchRequest() 调用方法里边的wrappedHandler.handleRequest()
-
BaseRestHandler.handleRequest() 再调用方法里边的prepareRequest()方法,到这一步,实际上会根据请求来选一个具体的action。prepareRequest()实际上是一个接口,可以看下边的实现类,红框只是一个案例(这就是一个删除索引对应的Action)在prepareRequest里边,将rest请求,转换成es内部认识的请求。
-
以一个案例来分析(RestDeleteIndexAction)
接着看到的是:
@Overridepublic RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(Strings.splitStringByCommaToArray(request.param("index"))); deleteIndexRequest.timeout(request.paramAsTime("timeout", deleteIndexRequest.timeout())); deleteIndexRequest.masterNodeTimeout(request.paramAsTime("master_timeout", deleteIndexRequest.masterNodeTimeout())); deleteIndexRequest.indicesOptions(IndicesOptions.fromRequest(request, deleteIndexRequest.indicesOptions())); return channel -> client.admin().indices().delete(deleteIndexRequest, new RestToXContentListener(channel));}
-
跟着第五步的 delete一直向下,走到的是ElasticsearchClient.execute(),这又是一个接口,接着跟到它的实现类,来到AbstractClient.execute(),调用doExecute(),这是一个抽象方法,它的实现类NodeClient.doExecute(),在方法中调用了executeLocally(),这个方法会调用transportAction(action).execute(),可以看到 action被执行了!
-
接着第6步,点进去transportAction(action).execute()来到了TransportAction.execute() 在这个类中,继续点击execute(),里边调用的是requestFilterChain.proceed(), 在向下走到proceed()里边,调用的是this.action.doExecute(task, request, listener),这个doExecute()是 TransportAction类中的方法,并且这个类是一个抽象类,于是根据doExecute看它的实现类,不同的功能也对应不同的action,还是以删除索引这个为例,