首页 > 解决方案 > 在运行 Solr 查询时,存活的代数不断增加

问题描述

我正在使用 jSolr (7.4) 测试一个查询,因为我相信它会导致我的程序出现内存泄漏。但是我不确定这是否确实是内存泄漏,所以我呼吁建议!

此方法在我的索引程序运行期间被多次调用(应该能够运行数周/数月而不会出现任何问题)。这就是我在使用 Netbeans Profiler 分析的循环中对其进行测试的原因。

如果我只是从给定索引中的所有文档(有 33k)中检索 id:

public class MyIndex {
    // This is used as a cache variable to avoid querying the index everytime the list of documents is needed
 private List<MyDocument> listOfMyDocumentsAlreadyIndexed = null;

 public final List<MyDocument> getListOfMyDocumentsAlreadyIndexed() throws SolrServerException, HttpSolrClient.RemoteSolrException, IOException {

  SolrQuery query = new SolrQuery("*:*");

  query.addField("id");
  query.setRows(Integer.MAX_VALUE); // we want ALL documents in the index not only the first ones

  SolrDocumentList results = this.getSolrClient().
    query(query).getResults();

    /**
    * The following was commented for the test, 
    * so that it can be told where the leak comes from.
    *
    */

    //            listOfMyDocumentsAlreadyIndexed = results.parallelStream()
    //                    .map((doc) -> { // different stuff ...
    //                                  return myDocument;
    //                                  })
    //                    .collect(Collectors.toList());

    return listOfMyDocumentsAlreadyIndexed; 
    /** The number of surviving generations 
     *  keeps increasing whereas if null is 
     * returned then the number of surviving 
     * generations is not increasing anymore
    */
}

我从分析器中得到这个(经过近 200 次运行,可以模拟我的程序一年的运行时间):

在此处输入图像描述

最幸存的对象是String

在此处输入图像描述

在查询索引中的所有文档时,不断增长的存活代数是否是预期的行为?

如果是这样,这是我在生产服务器上一段时间后得到的“OOM Java堆空间”错误的根本原因,因为它似乎来自stacktrace:

Exception in thread "Timer-0" java.lang.OutOfMemoryError: Java heap space
at org.noggit.CharArr.resize(CharArr.java:110)
at org.noggit.CharArr.reserve(CharArr.java:116)
at org.apache.solr.common.util.ByteUtils.UTF8toUTF16(ByteUtils.java:68)
at org.apache.solr.common.util.JavaBinCodec.readStr(JavaBinCodec.java:868)
at org.apache.solr.common.util.JavaBinCodec.readStr(JavaBinCodec.java:857)
at org.apache.solr.common.util.JavaBinCodec.readObject(JavaBinCodec.java:266)
at org.apache.solr.common.util.JavaBinCodec.readVal(JavaBinCodec.java:256)
at org.apache.solr.common.util.JavaBinCodec.readSolrDocument(JavaBinCodec.java:541)
at org.apache.solr.common.util.JavaBinCodec.readObject(JavaBinCodec.java:305)
at org.apache.solr.common.util.JavaBinCodec.readVal(JavaBinCodec.java:256)
at org.apache.solr.common.util.JavaBinCodec.readArray(JavaBinCodec.java:747)
at org.apache.solr.common.util.JavaBinCodec.readObject(JavaBinCodec.java:272)
at org.apache.solr.common.util.JavaBinCodec.readVal(JavaBinCodec.java:256)
at org.apache.solr.common.util.JavaBinCodec.readSolrDocumentList(JavaBinCodec.java:555)
at org.apache.solr.common.util.JavaBinCodec.readObject(JavaBinCodec.java:307)
at org.apache.solr.common.util.JavaBinCodec.readVal(JavaBinCodec.java:256)
at org.apache.solr.common.util.JavaBinCodec.readOrderedMap(JavaBinCodec.java:200)
at org.apache.solr.common.util.JavaBinCodec.readObject(JavaBinCodec.java:274)
at org.apache.solr.common.util.JavaBinCodec.readVal(JavaBinCodec.java:256)
at org.apache.solr.common.util.JavaBinCodec.unmarshal(JavaBinCodec.java:178)
at org.apache.solr.client.solrj.impl.BinaryResponseParser.processResponse(BinaryResponseParser.java:50)
at org.apache.solr.client.solrj.impl.HttpSolrClient.executeMethod(HttpSolrClient.java:614)
at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:255)
at org.apache.solr.client.solrj.impl.HttpSolrClient.request(HttpSolrClient.java:244)
at org.apache.solr.client.solrj.SolrRequest.process(SolrRequest.java:194)
at org.apache.solr.client.solrj.SolrClient.query(SolrClient.java:942)
at org.apache.solr.client.solrj.SolrClient.query(SolrClient.java:957)

将堆空间(“-Xmx”)从 8GB 增加到更大的容量肯定会解决问题还是会推迟它?可以做些什么来解决这个问题?

几个小时后编辑

如果null从被测方法返回 ( getListOfMyDocumentsAlreadyIndexed),则在整个测试过程中存活的世代数保持稳定:

在此处输入图像描述

因此,即使我没有使用此测试的查询结果(因为我只想关注泄漏发生的位置),看起来返回一个实例变量(即使它为空)也不是一个好主意。我会尝试删除它。

稍后再编辑

我注意到当我分析“定义的类”(“聚焦(仪器)”)时,遥测选项卡中幸存的世代仍在增加,而在分析“所有类”(“常规(采样)”)时它是稳定的。所以我不确定它是否解决了问题:

分析定义的类(重点)

分析所有类(抽样)

非常感谢任何提示:-)

标签: javasolr

解决方案


问题源于以下行:

query.setRows(Integer.MAX_VALUE);

根据这篇文章不应该这样做:

Solr 的 rows 参数可用于返回超过默认值的 10 行。我已经看到用户成功地将 rows 参数设置为 100-200 并且没有看到任何问题。但是,将 rows 参数设置得更高会产生很大的内存后果,应该不惜一切代价避免。

因此,问题已通过按照有关分页的 solr 文章按200 个文档块检索文档来解决:

SolrQuery q = (new SolrQuery(some_query)).setRows(r).setSort(SortClause.asc("id"));
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
boolean done = false;
while (! done) {
  q.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
  QueryResponse rsp = solrServer.query(q);
  String nextCursorMark = rsp.getNextCursorMark();
  doCustomProcessingOfResults(rsp);
  if (cursorMark.equals(nextCursorMark)) {
    done = true;
  }
  cursorMark = nextCursorMark;
}

请注意:您不应超过 200 个文档,setRows否则内存泄漏仍然会发生(例如 500 个确实会发生)。

现在,剖析器对幸存的世代提供了更好的结果,因为它们不再随时间增加。

在此处输入图像描述

但是,该方法要慢得多。


推荐阅读