mat*_*ler 84 php server-sent-events
所有,
HTML5 Rocks有一个很好的关于服务器发送事件(SSE)的初学者教程:
http://www.html5rocks.com/en/tutorials/eventsource/basics/
但是,我不明白一个重要的概念 - 什么触发服务器上导致消息发送的事件?
换言之-在HTML5例如-服务器仅仅发送时间戳一次:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$serverTime = time();
sendMsg($serverTime, 'server time: ' . date("h:i:s", time()));
Run Code Online (Sandbox Code Playgroud)
如果我正在构建一个实际的例子 - 例如,Facebook风格的"墙"或股票代码,其中服务器会在每次某些数据更改时将"新信息""推送"到客户端,这是如何工作的?
换句话说...... PHP脚本是否有一个连续运行的循环,检查数据的变化,然后每次发现一个消息时发送一条消息?如果是这样 - 你怎么知道何时结束这个过程?
或者 - PHP脚本是否只是发送消息,然后结束(如HTML5Rocks示例中的情况)?如果是这样 - 您如何获得持续更新?浏览器是否只是定期轮询PHP页面?如果是这样 - 那是一个"服务器发送的事件"?这与使用AJAX定期调用PHP页面的JavaScript中编写setInterval函数有什么不同?
对不起 - 这可能是一个非常天真的问题.但是我找不到的例子都没有说清楚.
[UPDATE]
我认为我的问题措辞不多,所以这里有一些澄清.
假设我有一个网页,应该显示Apple股票的最新价格.
当用户首次打开页面时,该页面会创建一个EventSource,其URL为我的"stream".
var source = new EventSource('stream.php');
Run Code Online (Sandbox Code Playgroud)
我的问题是 - "stream.php"应该如何工作?
像这样?(伪代码):
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.
function sendMsg($msg) {
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
flush();
}
while (some condition) {
// check whether Apple's stock price has changed
// e.g., by querying a database, or calling a web service
// if it HAS changed, sendMsg with new price to client
// otherwise, do nothing (until next loop)
sleep (n) // wait n seconds until checking again
}
?>
Run Code Online (Sandbox Code Playgroud)
换句话说 - 只要客户端"连接"它,"stream.php"是否保持打开状态?
如果是这样 - 这是否意味着您拥有与stream.php
并发用户一样多的线程运行?如果是这样 - 是远程可行的,还是构建应用程序的适当方式?你怎么知道什么时候可以结束一个实例stream.php
?
我的天真印象是,如果是这种情况,PHP 不适合这种服务器.但到目前为止我看到的所有演示都暗示PHP对此很好,这就是为什么我很困惑......
Lic*_*son 29
服务器发送的事件用于从服务器端到客户端的实时更新.在第一个示例中,不保留来自服务器的连接,并且客户端每3秒尝试再次连接,并使服务器发送的事件与ajax轮询没有区别.
因此,要使连接保持不变,您需要将代码包装在循环中并不断检查更新.
PHP是基于线程的,更多连接的用户将使服务器耗尽资源.这可以通过控制脚本执行时间来解决,并在脚本超过一定时间(即10分钟)时结束脚本.在EventSource
这样的延迟是在可接受的范围API将自动重新连接.
另外,查看我的PHP库以获取服务器发送的事件,您可以了解有关如何在PHP中执行服务器发送的事件以及使代码更容易理解的更多信息.
Dar*_*ook 24
"......只要客户与"连接","stream.php"会保持打开状态吗?"
是的,你的伪代码是一种合理的方法.
"你怎么知道何时可以结束stream.php的实例?"
在最典型的情况下,当用户离开您的站点时会发生这种情况.(Apache识别关闭的套接字,并杀死PHP实例.)从服务器端关闭套接字的主要时间是你知道一段时间内没有数据; 您发送给客户的最后一条消息是告诉他们在某个时间回来.例如,在您的股票流媒体案例中,您可以在晚上8点关闭连接,并告诉客户在8小时内回来(假设NASDAQ从凌晨4点到晚上8点开放报价).星期五晚上你告诉他们星期一早上回来.(我有一本关于SSE的新书,并在这个主题上专门介绍了几个部分.)
"...如果是这种情况,PHP对于这种服务器来说不是一种合适的技术.但到目前为止我看到的所有演示都暗示PHP对此很好,这就是为什么我这样做的原因困惑..."
好吧,人们认为PHP不适合普通的网站,而且它们是正确的:如果你用C++替换整个LAMP堆栈,你可以用更少的内存和CPU周期来完成它.然而,尽管如此,PHP还是为大多数网站提供了很好的功能.它是一种非常高效的Web工作语言,因为它结合了熟悉的类C语法和如此众多的库,并且对于管理人员来说是一个令人欣慰的语言,因为大量的PHP程序员可以雇用,有大量的书籍和其他资源,还有一些大的用例(例如Facebook和维基百科).这些基本上与您选择PHP作为流媒体技术的原因相同.
典型的设置不是每个PHP实例与NASDAQ的一个连接.相反,您将拥有另一个与NASDAQ连接的进程,或者可能是从群集中的每台计算机到NASDAQ的单个连接.然后将价格推入SQL/NoSQL服务器或共享内存.然后,PHP只会轮询共享内存(或数据库),并将数据推出.或者,拥有一个数据收集服务器,每个PHP实例打开一个到该服务器的套接字连接.数据收集服务器在收到每个PHP客户端时会推送更新,然后他们将这些数据推送到客户端.
使用Apache + PHP进行流式传输的主要可伸缩性问题是每个Apache进程的内存.当您达到硬件的内存限制时,做出业务决策,将另一台计算机添加到集群,或者将Apache从环路中删除,并编写专用的HTTP服务器.后者可以在PHP中完成,因此可以重用所有现有知识和代码,或者您可以用另一种语言重写整个应用程序.我的纯开发人员会用C++编写一个专用的,简化的HTTP服务器.我的经理会添加另一个盒子.