【问题标题】:Solr: missing content stream, Magento: error while reindexingSolr:缺少内容流,Magento:重新索引时出错
【发布时间】:2011-11-10 17:08:56
【问题描述】:

这把我逼疯了。

问题出现在一个双服务器系统中,其中服务器 A 运行 Magento EE 1.11,服务器 B 运行 Solr 3.4.0。两台服务器都在同一个网络 (192.168.x.x) 中,并且 A 上的 Magento 后端配置为使用 B 上的 Solr 守护程序进行目录搜索。

Imo,Magento 后端配置正确,因为 Magento Test Connection 功能始终返回 Successful! Test again?,我可以在 Solr 日志中找到由测试引起的 ping。

但是在尝试的时候

System -> Index Management -> Catalog Search Index -> Reindex data

Magento 总是以“重建索引过程出现问题”而失败。

检查 Solr 日志会导致缺少内容流并返回 HTTP 400(错误请求):

Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/admin/ping params={} hits=0 status=0 QTime=1
Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/admin/ping params={} status=0 QTime=2
Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/admin/ping params={} hits=0 status=0 QTime=1
Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/admin/ping params={} status=0 QTime=2
Nov 10, 2011 3:50:16 PM org.apache.solr.update.processor.LogUpdateProcessor finish
INFO: {} 0 0
Nov 10, 2011 3:50:16 PM org.apache.solr.common.SolrException log
SEVERE: org.apache.solr.common.SolrException: missing content stream
        at org.apache.solr.handler.ContentStreamHandlerBase.handleRequestBody(ContentStreamHandlerBase.java:62)
        at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:129)
        at org.apache.solr.core.SolrCore.execute(SolrCore.java:1368)
        at org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:356)
        at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:252)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
        at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
        at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:326)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
        at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/update params={wt=json&<delete fromPending="true"+fromCommitted%3D"true"><query>store_id:2</query></delete>} status=400 QTime=0
Nov 10, 2011 3:50:16 PM org.apache.solr.update.processor.LogUpdateProcessor finish
INFO: {} 0 0
Nov 10, 2011 3:50:16 PM org.apache.solr.common.SolrException log
SEVERE: org.apache.solr.common.SolrException: missing content stream
        at org.apache.solr.handler.ContentStreamHandlerBase.handleRequestBody(ContentStreamHandlerBase.java:62)
        at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:129)
        at org.apache.solr.core.SolrCore.execute(SolrCore.java:1368)
        at org.apache.solr.servlet.SolrDispatchFilter.execute(SolrDispatchFilter.java:356)
        at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:252)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1212)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:399)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
        at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
        at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:326)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
        at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Nov 10, 2011 3:50:16 PM org.apache.solr.core.SolrCore execute
INFO: [] webapp=/solr path=/update params={<rollback/>=&wt=json} status=400 QTime=0

在这个错误跟踪中,唯一让我觉得奇怪的是,在 /update 命令的参数中,= 中只有 一个 被 url 编码为 %3D ,但所有其他人都不是

<delete fromPending="true"+fromCommitted%3D"true"><query>store_id:2</query></delete>

Otoh 我对 Solr 很陌生,不知道这是否只是 Java 记录器本身的错误。

我还检查了Apache_Solr_Service::deleteByQuery(),这是产生失败 Solr 查询的 PHP 方法,但到目前为止找不到任何错误。

不幸的是,在这种情况下,生产环境绑定到 PHP 5.2.16,所以我想到的另一件事是在 PHP 5.2.16 下 htmlspecialcharsstream_context_set_optionfile_get_contents 可能存在问题,但 IIRC 没有不是这样的。

所以我的问题是:是什么导致了“缺少内容流”错误和/或如何解决这个问题?

【问题讨论】:

  • @zuloo:我正要支持你的 cURL 建议,但你似乎最近删除了你的答案。发生了什么?^^
  • 我只是想知道您是否注意到它 - 并且不确定它是否可以工作,因为我没有遇到此类问题,但在出于安全原因禁用 file_gets_content() 的环境中工作 - 只是认为它可能会起作用 - 我再次检查后取消删除它......
  • 我无法详细回答你的问题,这让我觉得我的回答可能只是废话或无关
  • @zuloo:不用担心,这不是废话。它可能无法解释原因或提供解决方法,但至少您提供了功能性解决方法。哪个imo总比没有好^^

标签: java magento solr


【解决方案1】:

在早期的 PHP 版本中存在一个已知错误,该版本使用“--with-curl-wrappers”构建。

你有没有用 curl 包装器编译过?尝试在没有的情况下重新编译,看看效果如何。

【讨论】:

  • 已检查。问题服务器实际上是编译-with-curl-wrappers。但是我看不到添加 cURL 上下文选项(这是 afaik -with-curl-wrappers 最终所做的)应该如何影响 PHP 的核心流处理。我的意思是,当完全使用 no cURL 方法时,就会出现问题。只需stream_content_set_option()file_get_contents()。介意解释一下为什么您认为 -with-curl-wrappers 可能是这里的问题吗?
  • 我之前遇到过几次这个问题,并且在没有 curl 包装器的情况下重新编译总是可以解决这个问题。至于我是怎么发现的,那是一个猜谜游戏,比较了我们设置的一堆不同的服务器和配置。
  • 我在另一台没有--with-curl-wrappers的机器上重新编译。另一台机器不完全是问题服务器的副本(操作系统和 Apache 版本略有不同,PHP 是相同的 5.2.16),但我可以确认,使用此编译没有 Magento 重新索引问题。我仍然不知道,whyhow 删除 cURL 包装器可能会影响 PHP 核心流处理,但我会将此作为修复。谢谢。
【解决方案2】:

我们重写了 enterprise/search/client/solr.php 以使用 curl。

您必须更改 _sendRawGet 和 _sendRawPost 方法:

protected function _sendRawGet($url, $timeout = FALSE)
{
    $curl = curl_init();
    curl_setopt ($curl, CURLOPT_URL,$url);
    curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
    if($timeout && is_numeric($timeout))
    {
        curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, floatval($timeout));
    }else{
        curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, floatval(5));
    }
    curl_setopt ($curl, CURLOPT_HEADER, 1);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: Basic " . base64_encode($this->getUserLogin() . ':' . $this->getPassword())));
    $ret = curl_exec($curl);
    $info = curl_getinfo($curl);
    if(curl_errno($curl))
    {
        throw new Exception('"' . curl_errno($curl) . '" Info: ' . print_r($info,true));
    }
    $header = substr($ret, 0, $info['header_size']);
    $body = substr($ret, -$info['download_content_length']);
    $response = new Apache_Solr_Response($body, explode("\r\n",$header), $this->_createDocuments, $this->_collapseSingleValueArrays);
    if ($response->getHttpStatus() != 200 && $response->getHttpStatus() != 100)
    {
        throw new Exception('"' . $response->getHttpStatus() . '" Status: ' . $response->getHttpStatusMessage(), $response->getHttpStatus());
    }
    curl_close($curl);
    return $response;
}


protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8')
{
    $curl = curl_init();
    curl_setopt ($curl, CURLOPT_URL,$url);
    curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
    if($timeout && is_numeric($timeout))
    {
        curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, floatval($timeout));
    }else{
        curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, floatval(5));
    }
    curl_setopt ($curl, CURLOPT_HEADER, 1);
    $sendHeader = array(
        "Authorization: Basic " . base64_encode($this->getUserLogin() . ':' . $this->getPassword()),
        "Content-Type: ".$contentType
    );
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $rawPost);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $sendHeader);
    $ret = curl_exec($curl);
    $info = curl_getinfo($curl);
    if(curl_errno($curl))
    {
         throw new Exception('"' . curl_errno($curl) . '" Info: ' . print_r($info,true));
    }
    $header = substr($ret, 0, $info['header_size']);
    $body = substr($ret, -$info['download_content_length']);
    $response = new Apache_Solr_Response($body, explode("\r\n",$header), $this->_createDocuments, $this->_collapseSingleValueArrays);
    if ($response->getHttpStatus() != 200 && $response->getHttpStatus() != 100)
    {
        throw new Exception('"' . $response->getHttpStatus() . '" Status: ' . $response->getHttpStatusMessage(), $response->getHttpStatus());
    }
    curl_close($curl);
    return $response;
}

也许这行得通,我们使用这种方法没有遇到任何问题

【讨论】:

    【解决方案3】:

    Magento EE 1.11.0.0 使用 stream_content_set_option()file_get_contents() 调用的组合来构建和执行 Solr 请求,因此问题似乎与 PHP 5.2.16 的 流处理 有关*.

    由于时间不多了,我刚刚重写了 Apache_Solr_Service 类并修改了方法 _sendRawGet()_sendRawPost() 以使用 cURL 请求而不是 PHP 流。

    到目前为止,此解决方法工作得非常好(顺便说一句:感谢@zuloo。我有同样的想法使用 cURL 解决方法,但只是想将其用作最后的手段)。

    我仍然想知道在使用 PHP 流时是什么导致了这个错误(同时我的主要嫌疑人是分块传输编码)。也许其他人路过并能提供一些启示,所以我暂时让这个问题悬而未决。


    * 这有点奇怪,因为根据Magento EE specs 应该只需要 PHP 5.2.13+。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多