PHP长轮询-“长”应该是多久?

3

当在PHP中使用长轮询时,例如:

$start_time = time();
while ((time() - $start_time) < 30) {
if ($db->getNewStuff()->rows > 0) {
    $response = "new stuff!";
    break;
}
usleep(1000000);
}
echo $response;

你如何评估“轮询”的时间间隔?在这个例子中,我选择了30秒,因为...我甚至无法解释为什么。

如果使用更长的轮询时间,比如几分钟,会有什么影响?Apache服务器会崩溃吗?我的应用程序会变得滞涨/卡顿/性能下降吗?

另外:进程中的 usleep 应该持续多久?

6个回答

2
您可以轻松饱和可用的Apache进程/工作线程。 例如,如果Apache配置如下所示:
StartServers       2
MinSpareServers    4
MaxSpareServers    8
ServerLimit        11
MaxClients         11
MaxRequestsPerChild  4000

你只能处理11个请求,然后你的网站将在至少30秒内无法访问。 如果你只是想证明概念,玩一下apache和PHP也没关系,但是在一个真正的服务器上,你确实应该避免使用PHP->Apache长轮询。
你需要使用类似彗星环境来实现可扩展的解决方案。

1
那就意味着如果当前有11个客户端正在轮询,其他人就无法以任何方式请求服务器了?那确实很糟糕。我想避免创建第二个处理服务器推送的服务器,但似乎不可避免... - F.P
确实,Apache并不适用于长轮询请求。对我来说,Nodejs看起来是一个很好的起点。让我们尝试一下这个聊天:http://chat.nodejs.org/ - Francesco Laurita

2

根据时间限制,您的PHP脚本可能无法长时间运行。因此,请确保(重新)设置时间限制。否则,增加次数不会有任何问题。

至于usleep应该持续多久,这是您需要自行进行基准测试的内容。较短的微睡眠将增加服务器负载,但更快地找到结果。适当的时间取决于您应用程序的其他部分和资源。您甚至可以根据服务器负载变化来调整微睡眠时间(即在服务器负载高时让其休眠更长时间)。


1

什么是长轮询

你提供的代码并不是长轮询。长轮询是指允许客户端等待某些事件,使用户界面能够立即响应服务器上的事件。

客户端发送一个常规的ajax请求。服务器端的代码可能会等待,也可能会立即响应。

如果没有要返回的内容(尚未发生事件),则只需使响应时间变长。如果发生了某个等待的事件,则立即发送响应。

客户端轮询您的ajax请求,该请求在某个事件发生之前不会响应,但是当该事件发生时,它会立即响应。客户端需要立即进行另一个长轮询请求。

防止错过事件

因此,通常在长轮询协议中使用序列号。每个事件都分配了一个序列号,新事件的序列号比旧事件高。如果您可以安排这样做,则可以使长轮询成为“获取自id以来的事件”请求。如果他们错过了事件,则会立即返回它们。如果他们给出了最新的序列号,则没有要返回的内容,因此不要返回任何响应,只需让其响应时间变长。

如果多个事件在长轮询之间 sneaked in,则您的轮询将返回多个事件记录。

这需要一种方法,让您的代码通知等待发送响应的代码。您可以将其实现为键值存储的合理速率轮询、某种进程间通信或适合重复使用的轻量级内容。

由于PHP的进程模型,您的选择有些受限。在nodejs或其他单进程服务器架构中,您可以使用一个简单的响应数组等待结果,并在发生新事件时调用它们所有,尊重每个响应的“since”参数。

经典案例

聊天客户端是这种情况的典型示例。聊天页面上的所有人都有一个长轮询等待着获取响应。页面正常工作,只是网络请求在后台花费时间。

当有人输入消息时,他们会将其发布到服务器上,并且处理程序会插入下一个ID的消息。所有长轮询都会注意到新记录大于它们正在查找的“since”值,并且立即为所有ID大于“since”参数的记录发送响应。从而在短时间内通知所有其他聊天参与者,而不使他们不断地检查新消息。


1

当调用usleep()时,PHP会一直等待直到休眠结束。

通常默认的最大脚本执行时间为30秒,但是sleep()和usleep()会持续更长时间,因为在休眠操作期间,PHP在技术上没有控制权。

我从未尝试过超过几分钟的休眠时间 - 也从未遇到任何问题。

如果有很多线程进入休眠状态,可能会出现处理其他请求的线程不足的情况...


你可以随时查看http://www.ape-project.org/ajax-push.html - 这听起来可能很有用,或者考虑使用其他更适合处理大量请求的httpd,例如lighttpd或nginx... - Brian

0

总响应时间超过20秒会使您的应用程序容易出现浏览器超时。请将其保持在20秒以下,以确保安全。


0
你应该真的考虑使用Node和Socket.io。 :)

我知道这些,而且我已经阅读了很多,但目前我想创建一个可以在任何网络托管服务上运行的应用程序...而使用Node/SocketIO是不可能的 - 但我很清楚它们的存在 :) - F.P
认真地说,不要给自己找麻烦。告诉你的客户他们需要使用VPS而不是那么吝啬。有时候你可以只花$5/月就能得到VPS。说真的,谁买不起呢?而且现在已经是2011年了,不是2001年。技术是我们最大的资产,坚持使用不满足你需求的技术(在这种情况下是PHP)会让你付出代价! - PaulM
在Francesco的回答之后,我想没有其他选择了。而且从SocketIO的工作原理来看,它确实是我需要的。我还发现了一个不错的PHP/NodeJS桥接器,可以让我在PHP中编写逻辑,同时使用NodeJS/SocketIO处理所有那些必须做的推送操作...这听起来像是一种可行的解决方案吗?或者在一个项目中混合使用语言是不好的? - F.P
我认为这取决于你。我自己有一个使用NodeJS/Socket.io的PHP项目,我会在PHP中做我需要做的事情。如果我需要进行PHP -> Node操作,则使用CURL来访问NodeJS端点。如果我需要将Socket.io发送到PHP,则只需进行Ajax Post。如果我需要将Socket.io发送到JS,则在我的JS中添加一个监听器。当你知道如何做时,这很简单 ;) - PaulM
感谢您的输入。我认为这也是我要走的路。只需要弄清楚如何在我的机器上运行这些东西就可以了 ;D - F.P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接