#java #magento #solr
#java #magento #solr
Вопрос:
Это сводит меня с ума.
Проблема возникает в двухсерверной системе, где на сервере A работает Magento EE 1.11, а на сервере B работает Solr 3.4.0. Оба сервера находятся в одной сети (192.168.x.x), а серверная часть Magento на A настроена на использование демона Solr на B для поиска по каталогу.
Имо, серверная часть Magento настроена правильно, так как Test Connection
функция Magentos всегда возвращается Successful! Test again?
, и я могу найти пинги, вызванные тестами, в журналах Solr.
Но при попытке
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=jsonamp;<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/>=amp;wt=json} status=400 QTime=0
Единственное, что мне почему-то кажется странным в этой трассировке ошибок, это то, что в параметрах /update
команды только одна из =
имеет URL-кодировку =
, а все остальные — нет.
<delete fromPending="true" fromCommitted%3D"true"><query>store_id:2</query></delete>
Otoh Я совсем новичок в Solr и понятия не имею, может быть, это просто ошибка самого Java logger.
Я также проверил Apache_Solr_Service::deleteByQuery()
PHP-метод, который выдает сбой запроса Solr, но пока не смог найти там никаких ошибок.
К сожалению, в данном случае производственная среда привязана к PHP 5.2.16, поэтому мне на ум пришла еще одна вещь — возможные проблемы с htmlspecialchars
, stream_context_set_option
или file_get_contents
под PHP 5.2.16, но IIRC таких не было.
Итак, мой вопрос: что вызывает ошибку «отсутствует поток содержимого» и / или как это исправить?
Комментарии:
1. @zuloo: Я собирался поддержать ваше предложение cURL, но вы, похоже, совсем недавно удалили свой ответ. Что произошло? ^^
2. Мне просто было интересно, заметили ли вы это — и не был уверен, что это может сработать, поскольку у меня не было таких проблем, но я работал в среде, где
file_gets_content()
отключен по соображениям безопасности — просто подумал, что это может сработать — я восстановил его, проверив еще раз…3. И я не смог подробно ответить на ваш вопрос, что заставило меня подумать, что мой ответ может быть просто дерьмовым или неактуальным
4. @zuloo: не беспокойтесь, это не было дерьмом. Возможно, это не объясняет причину или не позволяет устранить причину, но, по крайней мере, вы предоставили функциональный обходной путь. Что imo всегда лучше, чем ничего ^^
Ответ №1:
В ранних версиях PHP есть известная ошибка с выпусками, созданными с использованием «—with-curl-wrappers».
Вы случайно не компилировали с помощью оболочек curl? Попробуйте выполнить повторную компиляцию без этого и посмотрите, как у вас дела.
Комментарии:
1. Проверено. Проблемный сервер фактически был скомпилирован
-with-curl-wrappers
. Но я не вижу, как добавление параметров контекста cURL — что в конечном итоге делает afaik-with-curl-wrappers
— должно каким-то образом повлиять на обработку потока ядра PHPs. Я имею в виду, проблема возникает, когда никакие методы cURL вообще не используются. Простоstream_content_set_option()
иfile_get_contents()
. Не могли бы вы объяснить, почему вы думаете, что проблема с curl-оболочками может быть здесь?2. Я уже несколько раз сталкивался с этой проблемой, и повторная компиляция без оболочек curl всегда устраняет проблему. Что касается того, как я узнал, это была игра в угадайку и сравнение множества разных серверов и конфигураций, которые мы настроили.
3. Я выполнил перекомпиляцию на другой машине без
--with-curl-wrappers
. Другой компьютер не является точной копией проблемного сервера (версии OS и Apache немного отличаются, PHP тот же 5.2.16), но я могу подтвердить, что при использовании этой компиляции проблем с переиндексацией Magento нет. Я все еще не знаю, почему и как удаление оболочек 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 amp;amp; 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("rn",$header), $this->_createDocuments, $this->_collapseSingleValueArrays);
if ($response->getHttpStatus() != 200 amp;amp; $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 amp;amp; 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("rn",$header), $this->_createDocuments, $this->_collapseSingleValueArrays);
if ($response->getHttpStatus() != 200 amp;amp; $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 должен быть запрошен только PHP 5.2.13 .