//searchContext.timeoutInMillis()的值就是查询语句传入的timeout的值
final boolean timeoutSet = searchContext.timeoutInMillis() != SearchService.NO_TIMEOUT.millis();
if (timeoutSet && collector != null) { // collector might be null if no collection is actually needed
final Collector child = collector;
// TODO: change to use our own counter that uses the scheduler in ThreadPool
// throws TimeLimitingCollector.TimeExceededException when timeout has reached
collector = Lucene.wrapTimeLimitingCollector(collector, searchContext.timeEstimateCounter(), searchContext.timeoutInMillis());
if (doProfile) {
collector = new InternalProfileCollector(collector, CollectorResult.REASON_SEARCH_TIMEOUT,
Collections.singletonList((InternalProfileCollector) child));
}
}
try {
if (collector != null) {
if (doProfile) {
searchContext.getProfilers().getCurrent().setCollector((InternalProfileCollector) collector);
}
searcher.search(query, collector);
}
} catch (TimeLimitingCollector.TimeExceededException e) {
//如果查询超时searchTimedOut为true
assert timeoutSet : "TimeExceededException thrown even though timeout wasn't set";
queryResult.searchTimedOut(true);
} catch (Lucene.EarlyTerminationException e) {
assert terminateAfterSet : "EarlyTerminationException thrown even though terminateAfter wasn't set";
queryResult.terminatedEarly(true);
} finally {
searchContext.clearReleasables(SearchContext.Lifetime.COLLECTION);
}
SearchPhaseController的merge方法会合并结果,并得到是否超时
boolean timedOut = false;
Boolean terminatedEarly = null;
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : queryResults) {
QuerySearchResult result = entry.value.queryResult();
if (result.searchTimedOut()) {
//只要其中一个shard查询超时,整个查询语句就超时
timedOut = true;
}
if (result.terminatedEarly() != null) {
if (terminatedEarly == null) {
terminatedEarly = result.terminatedEarly();
} else if (result.terminatedEarly()) {
terminatedEarly = true;
}
}
totalHits += result.topDocs().totalHits;
if (!Float.isNaN(result.topDocs().getMaxScore())) {
maxScore = Math.max(maxScore, result.topDocs().getMaxScore());
}
}
......
InternalSearchHits searchHits = new InternalSearchHits(hits.toArray(new InternalSearchHit[hits.size()]), totalHits, maxScore);
return new InternalSearchResponse(searchHits, aggregations, suggest, shardResults, timedOut, terminatedEarly);
2 个回复
JackGe
赞同来自: CarrieJin 、rochy 、cccthought
SearchPhaseController的merge方法会合并结果,并得到是否超时
至于took的计算是当AbstractAsyncAction对象实例化(TransportSearchAction类的doExecute方法),把当前系统时间作为startTime的值,在请求最终结束时System.currentTimeMillis() - startTime。took是es内部真正处理时间,但不包括在search bulk排队的时间和从你程序所在节点的网络交互时间。
总结:timeout为到毫秒的整数,最小为1ms。查询结果中timed_out为true则表明至少一个shard执行lucene query时超时,查询因超时而返回,该lucene query结果不完整。另一种设置超时方法为在cluster settings中设置search.default_search_timeout。
yayg2008
赞同来自: cccthought