elasticsearch之請求處理流程(Rest/RPC )


.Action概述

 ES提供client供集群節點或java客戶端訪問集群用。client模塊通過代理模式,將所有的操作都集成到client接口中。這樣外部調用只需要初始化client就能夠完成所有的調用功能。在每個方法后面都有一個***action來承接相應的功能。elasticsearch中的絕大部分操作都是通過相應的action,這些action在action包中。它的結構如下圖所示:

 

上圖是action包的部分截圖,這里面對應着各個功能的action。各個action的包也都非常類似於index。這些action的實現也非常類似,都是基礎自action,下圖是indexaction的繼承關系:

因為這些action並未真正實現相應的功能,只是一個代理,因此實現上也非常簡單。他們的主要作用是提供新建response和request的方法及對應的action名稱。還拿indexaction為例,它的方法圖如下所示:

可以看到它只是提供了兩個新建response和request的方法,及一個字NAME字段,這個NAME字段會用於后面action調用中。每個action對應的功能實現是在對應的transportAction中。

 

實際上***action也並非是真正的功能實現者,它只是一個代理,它的真正實現者是transport***Action.在ES中,Transport*Action 是比較核心的類集合。這里至少有兩組映射關系。

Action -> Transport*Action
Transport*Action -> *TransportHandler

對應的功能是,可以通過Action 找到對應的TransportAction,這些TransportAction 如果是query類,則會調用SearchServiceTransportAction,並且通過第二層映射找到對應的Handler,否則可能就直接通過對應的Service完成操作。

 

第一層映射關系由類似下面的代碼在ActionModule中完成:

第二層映射目前看來只有在查詢相關的功能才有,其他的Transport*Action 則只調用對應的Service 來完成實際的操作。類似 SearchServiceTransportAction ,可以看做是SearchService進一步封裝。如下:

 

2.rest請求到action的映射

對於java的Client請求,可以直接找到對應的action請求,但是ES為了提供更為通用的restful請求,通過restControl進行了由http到action的映射。

首先,每一個action在初始化時,針對自身能處理的action向restController進行注冊,以RestCreateIndexAction為例,

    public RestCreateIndexAction(Settings settings, RestController controller, Client client) {
        super(settings, controller, client);
        controller.registerHandler(RestRequest.Method.PUT, "/{index}", this);
        controller.registerHandler(RestRequest.Method.POST, "/{index}", this);
    }

restController維護了幾個隊列,用來處理不同類型的http請求。

 /**
     * Registers a rest handler to be execute when the provided method and path match the request.
     */
    public void registerHandler(RestRequest.Method method, String path, RestHandler handler) {
        switch (method) {
            case GET:
                getHandlers.insert(path, handler);
                break;
            case DELETE:
                deleteHandlers.insert(path, handler);
                break;
            case POST:
                postHandlers.insert(path, handler);
                break;
            case PUT:
                putHandlers.insert(path, handler);
                break;
            case OPTIONS:
                optionsHandlers.insert(path, handler);
                break;
            case HEAD:
                headHandlers.insert(path, handler);
                break;
            default:
                throw new IllegalArgumentException("Can't handle [" + method + "] for path [" + path + "]");
        }
    }

 當httpServer收到請求時候,優先進行plugin處理,然后轉發給 RestController來處理。

    public void internalDispatchRequest(final HttpRequest request, final HttpChannel channel) {
        String rawPath = request.rawPath();
        if (rawPath.startsWith("/_plugin/")) {
            RestFilterChain filterChain = restController.filterChain(pluginSiteFilter);
            filterChain.continueProcessing(request, channel);
            return;
        } else if (rawPath.equals("/favicon.ico")) {
            handleFavicon(request, channel);
            return;
        }
        restController.dispatchRequest(request, channel);
    }

 RestController收到請求后,如果有filter,先進行r過濾。然后進行executeHandler,最后通過channel返回操作結果

void executeHandler(RestRequest request, RestChannel channel) throws Exception {
        final RestHandler handler = getHandler(request);
        if (handler != null) {
            handler.handleRequest(request, channel); //根據action注冊的path,調用對應action的handleRequest方法,在該方法內通過channel返回操作結果
} else { if (request.method() == RestRequest.Method.OPTIONS) { // when we have OPTIONS request, simply send OK by default (with the Access Control Origin header which gets automatically added) channel.sendResponse(new BytesRestResponse(OK)); } else { channel.sendResponse(new BytesRestResponse(BAD_REQUEST, "No handler found for uri [" + request.uri() + "] and method [" + request.method() + "]")); } } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM