我正在创建一个API,它从第三方组件中检索项目并以指定的XML / CSV / TEXT结构返回这些项目,管理员可以通过模板对其进行自定义。
问题:一个API请求可能很容易包含数百万个项目。因此,在内存方面不可能创建整个列表服务器端并将其发送给客户端。
相反,应该即时创建项目,并将结果立即发送到客户端,而不将它们存储在PHP的内存中。
这怎么可能?
示例模板:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<items>
{items}
<item no="{number}">{item}</item>
{/items}
</items>
没有流媒体的当前代码示例。实际上并没有工作,但你应该知道:
echo preg_replace_callback('@{items}(.*){/items}@si', function (array $matches)
{
return createItems($matches[1]);
}, $template);
function createItems($itemTemplate)
{
$items = '';
while (itemsExist()) {
$items .= getItem($itemTemplate);
}
}
我想,我应该停止缓冲var中的每个项目而不是直接回显它们?但是,如何保持XML的/ CSV / JSON结构完好无损或列表中的模板中的其他内容?
答案 0 :(得分:1)
如果您达到了在服务器上生成的结果集太大而无法放入内存的程度,那么您应该考虑API的客户端如何处理这么大的内容结果也是如此。
我已经看到有两种模式可以解决这类问题:
在API中使用分页来返回结果页面,就像在网页上一样。通常,这涉及向&#34;下一页&#34;提供URL。 API响应中结果集的结果。然后,客户端可以简单地迭代每个API响应,直到没有&#34;下一页&#34;响应中存在的URL,表示已到达结果集的末尾。
您的API响应如下所示:
{
items: [ { }, { } ... ],
next_page: "http://my.domain.com/results?page=2"
}
通过这种方法,您的客户将POST到您的API并立即获得令牌。
API将在后台执行整个响应的生成 - 通常使用消息队列系统,如RabbitMQ或SQS - 将结果保存到Web服务器上的文件中。请注意,这发生在HTTP请求之外,因此客户端在此过程中不会阻止Web服务器。
客户端定期轮询API,传递先前从API收到的令牌。最终,API将响应一些数据,以指示结果集已生成并准备下载。然后,API可以在其响应中包含结果集的内容,或者提供客户端可以从中下载结果集的URL。
还有第三种替代方案,但除非您计划为API使用者构建客户端库,否则我不会推荐它。您可以使用PHP的stream_ *函数来创建API将运行的流。这将允许您将数据推送到流上,并且您的客户端可以从流中读取数据,而不会消耗大量内存。但是,还有很多其他工作要做,特别是如果您需要客户端解析整个XML / JSON文档。
我会推荐分页。它易于推理,在API端实现并不困难,可重用并消除客户端和服务器端的内存消耗问题。