【问题标题】:Solr Out of memory exceptionSolr 内存不足异常
【发布时间】:2012-03-31 15:40:29
【问题描述】:

Solr 出现内存不足异常。索引大小很小,大约在 30GB 左右。完整索引已完成。稍后在搜索时,也许当它尝试将结果加载到内存中时,它开始给出这个异常。尽管分配给 Tomcat 的内存相同,并且另一台服务器上的 solr 配置副本完全相同,但它工作得非常好。我正在开发 64 位软件,包括 Windows 上的 Java 和 Tomcat。使用较小的索引大小,它工作得非常好。我正在考虑增加分配的 tomcat 堆空间,但是如何在具有完全相同系统和 solr 配置的不同服务器上运行良好? 任何帮助将不胜感激。

这里是日志:

服务器遇到内部错误(solr 配置中的严重错误。检查您的日志文件以获取有关可能错误的更多详细信息。如果您希望 solr 在配置错误后继续,请更改:false in null ----- -------------------------------------------------- ------ java.lang.RuntimeException: java.lang.OutOfMemoryError: Java 堆空间在 org.apache.solr.core.SolrCore.getSearcher(SolrCore.java:1068) 在 org.apache.solr.core.SolrCore .(SolrCore.java:579) 在 org.apache.solr.core.CoreContainer$Initializer.initialize(CoreContainer.java:137) 在 org.apache.solr.servlet.SolrDispatchFilter.init(SolrDispatchFilter.java:83) 在 org .apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:295) 在 org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:422) 在 org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig. java:115) 在 org.apache.catalina.core.StandardContext.filterStart(StandardCont ext.java:4072) 在 org.apache.catalina.core.StandardContext.start(StandardContext.java:4726) 在 org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799) 在 org.apache.catalina .core.ContainerBase.addChild(ContainerBase.java:779) 在 org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601) 在 org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943 ) 在 org.apache.catalina.startup.deployWARs(HostConfig.java:778) 在 org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504) 在 org.apache.catalina.startup.HostConfig。在 org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142) 在 org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142) 在 org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324) 开始(HostConfig.java:1317) .catalina.core.ContainerBase.start(ContainerBase.java:1065) 在 org.apache.catalina.core.StandardHost.start(StandardHost.java:840) 在 org.apache.catalina.core.ContainerBase.start(ContainerBase.java :1057) t org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463) 在 org.apache.catalina.core.StandardService.start(StandardService.java:525) 在 org.apache.catalina.core.StandardServer.start (StandardServer.java:754) 在 org.apache.catalina.startup.Catalina.start(Catalina.java:595) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) at org.apache。 catalina.startup.Bootstrap.main(Bootstrap.java:414) 原因:java.lang.OutOfMemoryError:org.apache.lucene.index.SegmentTermEnum.termInfo(SegmentTermEnum.java:180) 在 org.apache 处的 Java 堆空间。 lucene.index.TermInfosReader.(TermInfosReader.java:91) at org.apache.lucene.index.SegmentReader$CoreReaders.(SegmentReader.java:122) at org.apache.lucene.index.SegmentReader.get(SegmentRea der.java:652) 在 org.apache.lucene.index.SegmentReader.get(SegmentReader.java:613) 在 org.apache.lucene.index.DirectoryReader.(DirectoryReader.java:104) 在 org.apache.lucene。 index.ReadOnlyDirectoryReader.(ReadOnlyDirectoryReader.java:27) at org.apache.lucene.index.DirectoryReader$1.doBody(DirectoryReader.java:74) at org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java: 683) 在 org.apache.lucene.index.IndexReader.open(IndexReader.java:476) 在 org.apache.lucene.index.IndexReader .open(IndexReader.java:403) 在 org.apache.solr.core.StandardIndexReaderFactory.newReader(StandardIndexReaderFactory.java:38) 在 org.apache.solr.core.SolrCore.getSearcher(SolrCore.java:1057) 在 org. apache.solr.core.SolrCore.(SolrCore.java:579) 在 org.apache.solr.core.CoreContainer$Initializer.initialize(CoreContainer.java:137) 在 org.apache.solr.servlet.SolrDispatchFilter.init(SolrDispatchFilter .java:83) 在 org.apache.cat alina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:295) at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:422) at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:115 )在 org.apache.catalina.core.ContainerBase 的 org.apache.catalina.core.StandardContext.start(StandardContext.java:4726) 的 org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4072)。 addChildInternal(ContainerBase.java:799) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601) at org.apache .catalina.startup.HostConfig.deployWAR(HostConfig.java:943) 在 org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778) 在 org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java :504) 在 org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317) 在 org.apache.catalina.startup.HostConfig.lifecycleEv ent(HostConfig.java:324) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065) )阻止了它完成此请求。

【问题讨论】:

    标签: java tomcat solr lucene


    【解决方案1】:

    我认为您应该像对待任何其他 OOME 问题一样对待它:

    • 可能是您的应用程序只需要更多内存 - 修复:使用 JVM -Xmx 选项增加最大堆大小。

    • 可能是您的应用程序存在内存泄漏。 (可能在 Solr 中,也可能在您的代码中。) - 修复:使用内存分析器来识别泄漏并修复它。


    ...但是如何在具有完全相同系统和 solr 配置的不同服务器上运行良好?

    显然它们不一样。有些东西是不同的,但你无法弄清楚它是什么。 (但我不认为找出差异是解决问题的好方法。)

    【讨论】:

    • 谢谢斯蒂芬。实际上,这个问题与将 Tomcat 作为服务运行有关。我将为此发布另一个问题。
    【解决方案2】:

    当我将 Tomcat 作为服务运行时,它不会以某种方式将 CATALINA_OPTS 设置为环境变量,但是如果我使用 startup.bat 在控制台/命令行上运行 Tomcat,一切都很好。 我为我的后续问题发布了另一个问题:Tomcat as a service v/s Tomcat on console for 64 bit Windows

    【讨论】:

      【解决方案3】:

      那台服务器中有多少超过 30G 的 RAM?

      无论如何,您是否检查了top 中 SOLR 进程的 RSS?运行top 命令,然后按M(大写M)按内存使用对进程进行排序。观看 Resident Set 列,了解在加载数据、尝试各种查询以及使用各种 maxSegments 数字运行 optimize 时实际使用了多少 SOLR。从一个较大的数字开始,一次大约下降一半或三分之一。如果您可以在定期获取新更新的数据库中将其减少到 3 个段,这是合理的。

      更多关于优化的细节在这里:http://wiki.apache.org/solr/UpdateXmlMessages#A.22commit.22_and_.22optimize.22

      【讨论】:

        【解决方案4】:

        两台服务器是否具有相同的应用程序重启配置文件?

        我最近遇到了一个问题,即使用 SOLR 的客户端应用程序在应用程序重新启动时泄漏类加载器,因为 SOLR 客户端库中的 MultiThreadedHttpClientManager 启动一个 ReferenceQueueThread,除非这是显式关闭,否则应用程序类加载器将被固定,防止它在重新启动时被回收。

        这种情况的解决方法是添加一个在销毁时调用 MultiThreadedHttpClientManager.shutdownAll() 的 ServletContextListener。

        【讨论】: