solr中的SolrEventListener以及cache统计信息的获得

先声明一下,我的solr的版本是5.5.3

 

上一篇博客中说了当更新SolrIndexSearcher的时候并不是仅仅调用预热,还有其他的操作,那么都是有什么呢,看一下SolrCore的getSearcher方法(参数最多的一个),如果if (newSearcher != currSearcher) ,即索引发生了变化(无论是commit还是softCommit都算是变化),不仅仅是调用上一个博客中讲的warm,还有下面的操作:

if (currSearcher == null) {
    future = searcherExecutor.submit(new Callable() {
    @Override
    public Object call() throws Exception {
         try {
             for (SolrEventListener listener : firstSearcherListeners) {//循环firstSearcherListener,调用其newSearcher方法,第一个参数是新生成的searcher,第二个是null
                  listener.newSearcher(newSearcher, null);
                }
              } catch (Throwable e) {
                SolrException.log(log, null, e);
                if (e instanceof Error) {
                  throw (Error) e;
                }
              }
              return null;
            }
          });
        }

        if (currSearcher != null) {
          future = searcherExecutor.submit(new Callable() {
            @Override
            public Object call() throws Exception {
              try {
                for (SolrEventListener listener : newSearcherListeners) {//和上面的firstSearcherListener一样,只不过这里的参数的第二个是当前的searcher。
                  listener.newSearcher(newSearcher, currSearcher);
                }
              } catch (Throwable e) {
                SolrException.log(log, null, e);
                if (e instanceof Error) {
                  throw (Error) e;
                }
              }
              return null;
            }
          });
        }

上面的firstearcherListener和newSearcherListener都是 List<SolrEventListener>,即多个SolrEventListener,可以总结当切换SolrIndexSearcher的时候就会触发我们配置的listener的newSearcher方法,并且对于不同的名字(firstSearcherListener还是newSearcherListener)传入的参数还是不一样的。

 

如何配置监听呢?我是参考的这个博客:http://blog.csdn.net/duck_genuine/article/details/7862454

具体的配置为在solrconfig.xml中的<query></query>中添加下面的代码:

<listener event="newSearcher" class="com.comall.solr.listener.HelloWordListener">  <!--这个是配置的newSearcher,即传入新旧SolrIndexSearcher两个参数的-->
	<arr name="sortFields">   <!-- arr是封装为arraylist -->
		<str>title</str>  <!-- str是字符串 -->
		<str>id</str>  
	</arr>
	<!-- str是字符串 -->
	<str name="queryKeyFile">/Users/yzygenuine/56workspace/solr_jetty/solr/extConf/query.txt</str>  	
	<arr name="queries">  
		<lst> <!--lst是封装为NamedList  org.apache.solr.common.util.NamedList   这里的封装的结果是我做实验做出来的 -->
			<str name="q">solr</str>
			<str name="qt">standard</str>
			<str name="sort">price desc</str>
		</lst>  
	</arr>  
</listener>  

 我的HelloWordListener的代码为:

public class HelloWordListener extends AbstractSolrEventListener {//继承自org.apache.solr.core.AbstractSolrEventListener
	static Logger logger = LoggerFactory.getLogger(HelloWordListener.class);
	public HelloWordListener(SolrCore core) {
		super(core);
		logger.info("初始化HelloWordListener");
	}
	@Override
	public void init(@SuppressWarnings("rawtypes") NamedList args) {//初始化,args即配置的参数,我用这个来检测封装的类型。
		
		super.init(args);
		StringBuffer buffer = new StringBuffer();
		Object sortFields = args.get("sortFields");
		
		buffer.append("sortFields的类型是:")
			.append(sortFields.getClass().getName())
			.append("---")
			.append("queryKeyFile的类型是:");
		
		Object queryKeyFile = args.get("queryKeyFile");
		buffer.append(queryKeyFile.getClass().getName()).append("---").append("queries的类型是:");
		
		Object que = args.get("queries");
		buffer.append(que.getClass().getName()).append(",queries的第一个元素的类型是:").append(((ArrayList)que).get(0).getClass().getName())
			.append(",query的第一个元素是:").append(((ArrayList)que).get(0));
			
		logger.info("初始化参数是:{}", buffer.toString());
//		{sortFields=[title, id],queryKeyFile=/Users/yzygenuine/56workspace/solr_jetty/solr/extConf/query.txt,queries=[{q=solr,qt=standard,sort=price desc}]}	
	}
	@Override
	public void postCommit() {
		logger.info("调用postCommit");
	}
	@Override
	public void postSoftCommit() {
		logger.info("调用SoftCommit");
	}
	@Override
	public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {//调用newSearcher,从结果来看的确是将两个searcher都传入进去了,并且这个也对softCommit做了测试,如果没有更新索引,softCommit是不会造成已经注册的SolrINdexSearcher发生变化的
		logger.info("调用newSearcher:newSearcher:{},currentSearcher:{}",new Object[]{newSearcher,currentSearcher});		
	}
}

 

本来我是抱着很大的希望使用这个listener的,我的本意是能够通过SolrIndexSearcher来获得里面的多个缓存,然后得到这些缓存的统计信息,但是遗憾的是SolrIndexSearcher并没有给我们方法来得到这些缓存(我本人是比较讨厌使用反射那种暴力操作的)。不过在  http://blog.csdn.net/duck_genuine/article/details/7862454  这篇博客中我有点启发——即我们使用这个新的searcher来做一些提前的搜索,这样不就能实现指定的热身了么,不过我自己倒是没有测试过,等需要的时候再做些测试吧。http://blog.csdn.net/duck_genuine/article/details/7862454,这个博客的主人看来对solr的研究不错,是个大神。

 

//下面的是后来补充的,

上面说我没有找到获得SolrIndexSearcher中cache的方法,现在找到了,在solrCore中有个getInfoRegistry方法,就是获得所有的当前注册的SolrIndexSearcher的信息的,这个方法在一个新的SolrIndexSearcher注册的时候调用,我们看一下注册方法:

  /** Register sub-objects such as caches   */
  public void register() {
    // register self 
    core.getInfoRegistry().put("searcher", this);//调用solrCore的getInfoRegistry方法
    core.getInfoRegistry().put(name, this);
    for (SolrCache cache : cacheList) {//这里的cacheList包括我们在solrConf.xml中配置的所有的cache,比如FilterCache,queryResultCache,DocumentCache,fieldValueCache,以及使用<cache>自定义的多个cache。
      cache.setState(SolrCache.State.LIVE);
      core.getInfoRegistry().put(cache.name(), cache);//将多个cache放入到core中,这样就会覆盖原来的cache。
    }
    registerTime = new Date();
  }

 这样我们就可以通过调用solrCore.getInfoRegistry来获得之前的SolrIndexSearcher的各种cache,然后获得其统计信息了。我改写的HelloWordListener的newSearcher代码如下:

public static final String filterCache_name = "filterCache";
public static final String queryResultCache_name = "queryResultCache";
public static final String documentCache_name = "documentCache";
public static final String fieldValueCache_name = "fieldValueCache";

@Override
public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
	Map<String, SolrInfoMBean> info = getCore().getInfoRegistry();
		
	SolrInfoMBean filterCache = (SolrInfoMBean) info.get(filterCache_name);
	logger.info(filterCache.getStatistics().toString());
	
	SolrInfoMBean queryCache = info.get(queryResultCache_name);
	logger.info(queryCache.getStatistics().toString());
	
	SolrInfoMBean documentCache = info.get(documentCache_name);
	logger.info(documentCache.getStatistics().toString());
	
	logger.info(info.get(fieldValueCache_name)==null?"fieldvalueCache是null":"fieldValueCache不是null");
}

 这样就能从控制台发现solr的缓存的使用情况了。在查询几次之后,提交一个新的document,这样就会调用listener,我自己做的测试的结果为:

{lookups=0,hits=0,hitratio=0.0,inserts=0,evictions=0,size=0,warmupTime=0,cumulative_lookups=0,cumulative_hits=0,cumulative_hitratio=0.0,cumulative_inserts=0,cumulative_evictions=0}//filterCache的
{lookups=26,hits=23,hitratio=0.88,inserts=3,evictions=0,size=3,warmupTime=0,cumulative_lookups=26,cumulative_hits=23,cumulative_hitratio=0.88,cumulative_inserts=3,cumulative_evictions=0}//queryResultCache的
{lookups=32,hits=22,hitratio=0.69,inserts=10,evictions=0,size=10,warmupTime=0,cumulative_lookups=32,cumulative_hits=22,cumulative_hitratio=0.69,cumulative_inserts=10,cumulative_evictions=0}//documentCache的
fieldValueCache不是null//可以发现fieldValueCache自己就会创建,尽管在solrconf.xml中没有配置。

 

 

 

猜你喜欢

转载自suichangkele.iteye.com/blog/2365868