我有一个PHP SOAP Web服务,使用CakePHP,它将可变数量的数据返回给客户端。返回的数据量可能非常少或很大(> 10MB但<100MB)。
我遇到的问题是,响应越大(通常大于5 MB),应用程序内存不足,事情就会崩溃。我尝试改变的第一件事是使用原始SQL查询而不是Cake的数据访问级别。这样,当我从数据库中检索10,000条记录时,Cake不会尝试将其全部保存在内存中。
虽然这是一个糟糕的惯例,但效果确实很好。然而,更大的问题是,一旦我得到结果,它仍会耗尽内存传输响应。我不确定当SoapServer编译响应时是否发生这种情况,或者客户端内存不足以存储响应,或者内存耗尽时只是在屏幕上序列化/呈现数据。
在任何情况下,似乎有一些方法可以将SOAP响应流回客户端,一切都会好得多。无论出现什么问题,数据都可以分解为可管理的块。我不知道如何在PHP中执行此操作,或者甚至可能。
请告知。
答案 0 :(得分:2)
您应该收到一条错误消息,告诉您内存耗尽的内容。理论上,这应该可以帮助您确定失败的原因。我的猜测是SOAPServer在发送响应之前将响应存储在内存中,可能是因为它使用PHP DomDocument构建XML DOM。 DomDocument(或者可能是SimpleXML)的缺点是必须将整个文档处理到内存中并在将数据序列化为XML之前作为DOM文档有效。
流式传输大量XML数据的更好方法是使用PHP的XMLWriter扩展名。与DOM不同,它不需要将整个文档存储到内存中,它希望您处理文档验证。您可以使用此扩展程序使用XMLWriter::openUri函数直接输出到HTTP响应。这意味着您可以按顺序执行以下操作,并且具有最小的内存开销:
php://output
的{{3}}函数为URI创建XMLWriter的实例。这会将所有内容推送到输出(类似于print / echo)并在内存中存储(几乎)任何内容。确保您已经推出了您需要的任何标题,Cookie等,就像任何其他输出检查一样。作为旁注,XMLWriter::openUri的反面是XMLWriter,如果您在读取由于内存限制而无法使用常规方法打开的大型XML文件时会感到很麻烦。