Большой поток SOAP-ответа в PHP - PullRequest
0 голосов
/ 03 марта 2011

У меня есть веб-сервис PHP SOAP, использующий CakePHP, который возвращает переменное количество данных обратно клиентам. Количество возвращаемых данных может быть очень маленьким или огромным (> 10 МБ, но <100 МБ). </p>

Проблема, с которой я столкнулся, заключается в том, что при больших откликах (обычно больше 5 МБ) приложению не хватает памяти и происходит сбой. Первое, что я попробовал изменить, - это использовать необработанные SQL-запросы, а не уровень доступа к данным Cake. Таким образом, когда я получу 10000 записей из базы данных, Cake не будет пытаться сохранить все это в памяти.

Это сработало очень хорошо, хотя это плохое соглашение. Однако большая проблема заключается в том, что, как только я получу результаты, все равно не хватит памяти для передачи ответа. Я не уверен, происходит ли это, когда SoapServer компилирует ответ, или если клиенту не хватает памяти для хранения ответа, или если ему не хватает памяти, просто сериализуя / отображая данные на экране.

В любом случае, похоже, что если бы был какой-то способ отправить ответ SOAP обратно клиенту, все работало бы намного лучше. Независимо от того, в чем проблема, данные могут быть разбиты на управляемые куски. Я не знаю, как сделать это в PHP, хотя, или если это вообще возможно.

Пожалуйста, сообщите.

1 Ответ

2 голосов
/ 03 марта 2011

Вы должны получить сообщение об ошибке, сообщающее, что исчерпало память. Теоретически, это должно помочь вам определить, что не работает. Я предполагаю, что SOAPServer хранит ответ в памяти перед отправкой ответа, вероятно потому, что он строит XML DOM с использованием PHP DomDocument . Недостатком DomDocument (или, возможно, SimpleXML) является то, что весь документ должен быть обработан в памяти и действителен как документ DOM, прежде чем данные могут быть сериализованы в XML.

Лучшим способом потоковой передачи больших кусков данных XML было бы использование расширения PHP XMLWriter . В отличие от DOM, ему не нужно хранить весь документ в памяти, и он ожидает, что вы обработаете проверку документа. Это расширение можно использовать для вывода непосредственно в ответ HTTP с помощью функции XMLWriter :: openUri . Это означает, что вы можете выполнять следующие операции по порядку и иметь минимальные накладные расходы памяти:

  1. Открыть соединение с базой данных
  2. Поиск нужного вам материала
  3. Создайте экземпляр XMLWriter , используя функцию XMLWriter :: openUri с параметром php://output для URI. Это подтолкнет все к выводу (аналогично print / echo) и ничего не сохранит в памяти. Сначала убедитесь, что вы уже вытеснили все заголовки, файлы cookie и т. Д., Как и любую другую проверку вывода.
  4. Создание преамбулы SOAP.
  5. Переберите элементы, которые вы собираетесь вернуть в ответе мыла, добавив элементы в вывод.
  6. Создание SOAP-поста

В качестве примечания, обратное значение XMLWriter равно XMLReader , если вы заинтересованы в чтении больших файлов XML, которые нельзя открыть обычными методами из-за ограничений памяти.

...