elasticsearch源碼分析之search模塊(client端)
注意,我這里所說的都是通過rest api來做的搜索,所以對於接收到請求的節點,我姑且將之稱之為client端,其主要的功能我們可以簡單地概括為將的數據請求發送到node,然后在對返回的結果做處理並返回給調用方,話雖如此,但是過程並非那么簡單。
請求初始化
1、api的注冊,上一篇已經提到了,所以的api都是通過Guice框架注冊進來的,在注冊的時候會在controller上將不同的url綁定到不同的handler中:
controller.registerHandler(GET, "/_search", this); controller.registerHandler(POST, "/_search", this); controller.registerHandler(GET, "/{index}/_search", this); controller.registerHandler(POST, "/{index}/_search", this); controller.registerHandler(GET, "/{index}/{type}/_search", this); controller.registerHandler(POST, "/{index}/{type}/_search", this); controller.registerHandler(GET, "/_search/template", this); controller.registerHandler(POST, "/_search/template", this); controller.registerHandler(GET, "/{index}/_search/template", this); controller.registerHandler(POST, "/{index}/_search/template", this); controller.registerHandler(GET, "/{index}/{type}/_search/template", this); controller.registerHandler(POST, "/{index}/{type}/_search/template", this);
上述的url都屬於search的范疇,
2、當接收到請求后,client端會parseSearchRequest,對於請求進行解析,解析結果用一個SearchRequest來表示,我們來看看包含哪些內容:
其他的不多說,特別地,對於source的解析是核心所在,由parseSearchSource來完成,返回一個SearchSourceBuilder,其主要包含:
private QuerySourceBuilder querySourceBuilder; private QueryBuilder postQueryBuilder; private BytesReference filterBinary;
其實就相當於分解動作了,所以的search不外乎都是由這些要素組成,主要包括query、filter、aggs等等。
請求的執行
1、接下來,client會將send request:client.search(searchRequest, new RestStatusToXContentListener<SearchResponse>(channel));,其中channel用於處理回調,返回的類型為SearchResponse。
2、對應action的構建:
public void search(final SearchRequest request, final ActionListener<SearchResponse> listener) { execute(SearchAction.INSTANCE, request, listener); }
其中SearchAction.INSTANCE就是一個search action的實例。listener監聽回調。
3、用proxy來發送請求到server,上面的proxy其實是一個TransportProxyClient的實例,在Transport模塊中其實已經說過了,請求都是由proxy的發送的:
protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) { proxy.execute(action, request, listener); }
底層還是調用的TransportService的sendRequest,而發送到的node由DiscoveryNode node = nodes.get((index) % nodes.size());來決定,可以理解為輪訓選取一個node(其實這里看到的和我之前的理解是有些大不一樣了,我一直以為client端是直接發送給不同的shard所在的node上,再把結果合並起來的,難道之前理解是錯的???)。
獲取到從node返回的結果之后。由listener通過channel返回給調用方。
總結
client端的工作大體就是這么些了,下一遍再來說說在server端的工作了,server端的會比較麻煩一點,查詢還會分query、fetch上面的,下一篇再見咯。
