自定义SolrEventListener实现searcher的autowarm策略
在solrconfig.xml上可以配置在newSearcher和firstSearcher的监听器,在事件触发时,可以做某些热身搜索,让Searcher做好准备提供服务,特别是服务重启的时候,如果没有做好热身,开始提供服务搜索时都很勉强。
但原生的配置比较麻烦,如果要做多个搜索请求时,单纯在配置文件上配置略显得麻烦:
<listener event="newSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <lst><str name="q">美女</str><str name="qt">standard</str><str name="sort">rtsTime desc</str></lst> <lst><str name="q">hadoop</str><str name="qt">standard</str><str name="sort">rtsTime desc</str></lst> <lst><str name="q">zoie</str><str name="qt">standard</str><str name="sort">rts desc</str></lst> <lst><str name="q">lucene</str><str name="qt">standard</str><str name="sort">pubdate desc</str></lst> <lst><str name="q">new searcher</str><str name="qt">standard</str><str name="sort">sourceId desc</str></lst> <lst><str name="q">solr</str><str name="qt">standard</str><str name="sort">price desc</str></lst> </arr> </listener>
现在扩展写另一个事件监听器,可以指定需要加载的某些字段,在预热后加载字段缓存,用于排序或者函数搜索使用的。
增加每天的热词搜索,每行一个词,比如1000个词。
主要扩展的代码如下:
package org.apache.solr.core; import java.io.File; import java.io.IOException; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.request.SolrQueryResponse; import org.apache.solr.search.DocIterator; import org.apache.solr.search.DocList; import org.apache.solr.search.SolrIndexSearcher; /** * @author yzygenuine * */ public class MyQuerySenderListener extends AbstractSolrEventListener { /** * 查询词文件路径 */ private final static String QUERYKEY_FILE = "queryKeyFile"; /** * 需要缓存的字段数组 */ private final static String SORT_FILEDS = "sortFields"; public MyQuerySenderListener(SolrCore core) { super(core); } @Override public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) { List<String> sortFields = (List<String>) args.get(SORT_FILEDS); final SolrIndexSearcher searcher = newSearcher; NamedList sortParams = null; if (sortFields != null && !sortFields.isEmpty()) { sortParams = new NamedList(); for (int i = 0; i < sortFields.size(); i++) { sortParams.add(CommonParams.SORT, sortFields.get(i) + " desc"); } } String queryKeyFilePath = (String) args.get(QUERYKEY_FILE); String qt=(String)args.get(CommonParams.QT); boolean isDone = false; if (queryKeyFilePath != null && !queryKeyFilePath.isEmpty()) { log.info("###############################queryKeyFilePath:" + queryKeyFilePath); File f = new File(queryKeyFilePath); if (f.exists() && f.canRead()) { try { List<String> keys = FileUtils.readLines(f, "utf-8"); if (keys != null) { for (String k : keys) { if(k.isEmpty()||k.trim().isEmpty())continue; NamedList params = new NamedList(); if (sortParams != null) { params.addAll(sortParams); } params.add(CommonParams.Q, k); if(qt!=null&&!qt.isEmpty()){ params.add(CommonParams.QT, qt); } reqLocal(params, searcher, currentSearcher); } isDone = true; } } catch (Exception e) { log.error("", e); isDone = false; } } } if (!isDone) { try { log.info("just req sortFields params"); reqLocal(sortParams, searcher, currentSearcher); } catch (IOException e) { log.error("", e); } } log.info("QuerySenderListener sending requests to " + newSearcher); for (NamedList nlst : (List<NamedList>) args.get("queries")) { try { reqLocal(nlst, searcher, currentSearcher); } catch (Exception e) { } } log.info("QuerySenderListener done."); } /** * @param nlst * @param newSearcher * @param currentSearcher * @throws IOException */ private void reqLocal(NamedList nlst, final SolrIndexSearcher newSearcher, final SolrIndexSearcher currentSearcher) throws IOException { if (nlst == null) { nlst = new NamedList(); } NamedList params = addEventParms(currentSearcher, nlst); LocalSolrQueryRequest req = new LocalSolrQueryRequest(core, params) { @Override public SolrIndexSearcher getSearcher() { return newSearcher; } @Override public void close() { } }; SolrQueryResponse rsp = new SolrQueryResponse(); core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp); NamedList values = rsp.getValues(); for (int i = 0; i < values.size(); i++) { Object o = values.getVal(i); if (o instanceof DocList) { DocList docs = (DocList) o; for (DocIterator iter = docs.iterator(); iter.hasNext();) { newSearcher.doc(iter.nextDoc()); } } } req.close(); } }
新的监听器的配置如下:
<listener event="newSearcher" class="solr.MyQuerySenderListener"> <arr name="sortFields"> <str>title</str> <str>id</str> </arr> <str name="queryKeyFile">/Users/yzygenuine/56workspace/solr_jetty/solr/extConf/query.txt</str> <arr name="queries"> <lst><str name="q">solr</str><str name="qt">standard</str><str name="sort">price desc</str></lst> </arr> </listener>
firstSearcher也可以同样配置
转贴请声明: