Solr:缺少内容流,Magento:重建索引时出错

时间:2011-11-10 17:08:56

标签: java magento solr

这个让我疯了。

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

Imo,Magento后端配置正确,因为Magentos 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下htmlspecialcharsstream_context_set_optionfile_get_contents可能出现的问题。 16,但是IIRC没有这样的。

所以我的问题是:导致“缺少内容流”错误的原因和/或如何解决此问题?

3 个答案:

答案 0 :(得分: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;
}

也许这样可行,我们使用这种方法没有任何问题

答案 1 :(得分:2)

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

你是否有机会使用curl包装器进行编译?尝试重新编译,看看你的情况。

答案 2 :(得分:0)

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+。