每一個搜索請求都會持有一個searcher的引用,而不是創建一個新的searcher,處理完后會釋放掉這個引用。
Solr在初始化化時,通過SolrCore核心類要做很多的初始化工作,包過讀取solrconfig.xml配置文件里的內容,代碼如下:
booleanQueryMaxClauseCount(); //設置布爾查詢最多個數。
initListeners(); //讀取配置文件的search實例的監聽器。
initDeletionPolicy();
initIndex();
initWriters();
initQParsers();
initValueSourceParsers();
this.searchComponents = loadSearchComponents();
// Processors initialized before the handlers
updateProcessorChains = loadUpdateProcessorChains();
reqHandlers = new RequestHandlers(this);
reqHandlers.initHandlersFromConfig( solrConfig );
highlighter = initHighLighter();
// Handle things that should eventually go away
initDeprecatedSupport();
loadSearchComponents方法就是初始化indexSearch實例。詳細說明如下:
getSearcher – (forceNew, returnSearcher, waitSearcher-Futures)
關注solr全局三個點調用getSearcher函數 : solrCore初始化時(false, false, null),QueryComponent處理查詢
請求時(false, true, null),UpdateHandler在處理commit請求時(true, false, new Future[1])
---------
1.solrCore初始化時
根據solrconfig配置的IndexReaderFactory&DirectoryFactory獲取索引的IndexReader,再使用這個reader
封裝一個SolrIndexReader,再使用這個SolrIndexReader封裝一個RefCounted(searcher的引用計數器,當搜索
組件獲取一個組件后引用++,用完后調用close引用--,當引用數為0時將這個引用從core管理的一個當前被使用的
searcher的鏈表移除,同時調用searcher.close回收資源),將這個引用添加到core管理的一個當前被使用的searcher
的鏈表里如果firstSearcherListeners不為空則回調這些監聽器,這個回調是交給core的一個newSingleThreadExecutor去
做的,再往這個線程池里添加一個任務:將這個RefCounted設置為core當前最新的searcher的引用計數器
最后返回null,因為returnSearcher=false
在solrCore初始化時這樣做的主要目的是在初始化時就加載好IndexSearcher,搜索請求來了之后能立即返回,
而不必等待加載IndexSearcher
---------
2.QueryComponent處理查詢請求時
由于core當前最新的searcher的引用計數器不為null且這個獲取IndexSearcher的請求不是強制要求獲取最新的,且
returnSearcher=true故直接返回core當前最新的searcher的引用計數器,且這個引用計數器做++
這里面還有段當前searcher的引用計數器為null的邏輯,但是沒有發現有什么情況會導致這種情況發生故不累述了
---------
3.UpdateHandler在處理commit請求時
首先到core管理的一個當前被使用的searcher的鏈表里獲取目前最新的searcher;同時會加載索引目錄下的
index.properties文件(如果存在的話),拿到KEY=’index’的值,其指明目前索引的存放地方;如果獲取的目錄和當前
最新的searcher使用的目錄一致且solrConfig.reopenReaders為true則獲取通過searher.reader.reopen獲取
最新的reader -> 封裝成searcher,否則直接IndexReader.open獲取reader。
獲取到searcher后的一段邏輯[RefCount封裝,添加到searchers鏈表]和core初始化時是一樣的,接下來的邏輯是
如果solrConfig.useColdSearcher為TRUE其當前searcher的引用為null-導致來自QueryComponent的請求阻塞
[現在還沒發現什么情況會導致searcher的引用為null]
立即將這個新的searcher的引用設置為core當前最新的searcher的引用計數器,這樣來自QueryComponent的請求
拿到這個引用后返回,當時這時這個新建的searcher是沒有經過其前一個searcher的cache熱身的,同時這樣會導致這個
新建的searcher不會進行熱身活動
如果solrConfig.useColdSearcher為FALSE則會往線程池里添加一個熱身的任務
如果newSearcherListeners不為空則回調這些監聽器,也是給線程池的任務
最后如果先前沒有做將新的searcher的引用設置為core當前最新的searcher的引用計數器的行為的話,則往線程池添加
一個任務 – 將新的searcher的引用設置為core當前最新的searcher的引用計數器
最后返回null,因為returnSearcher=false
from:http://blog.sina.com.cn/s/blog_56fd58ab0100v3tp.html