php - 服务器发送的事件和 php - 什么触发服务器上的事件?

标签 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()));

如果我正在构建一个实际示例 - 例如,Facebook 风格的“墙”或股票行情,其中服务器会在每次某些数据更改时向客户端“推送”一条新消息,如何那行吗?

换句话说... PHP 脚本是否有一个循环持续运行,检查数据的变化,然后在每次找到时发送一条消息?如果是这样 - 你怎么知道什么时候结束这个过程?

或者 - PHP 脚本是否只是发送消息,然后结束(在 HTML5Rocks 示例中似乎就是这种情况)?如果是这样 - 您如何获得持续更新?浏览器是否只是定期轮询 PHP 页面?如果是这样 - 那是一个“服务器发送的事件”吗?这与在 JavaScript 中使用 AJAX 定期调用 PHP 页面的 setInterval 函数有何不同?

抱歉 - 这可能是一个非常幼稚的问题。但是我找到的例子都没有说明这一点。

[更新]

我认为我的问题措辞不当,所以在这里澄清一下。

假设我有一个网页应该显示 Apple 股票的最新价格。

当用户第一次打开页面时,页面会使用我的“流”的 URL 创建一个 EventSource。

var source = new EventSource('stream.php');

我的问题是——“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
    }
?>

换句话说 - 只要客户端“连接”到它,“stream.php”就保持打开状态吗?

如果是这样 - 这是否意味着运行 stream.php 的线程数与并发用户数一样多?如果是这样 - 这是远程可行的,还是构建应用程序的适当方式?你怎么知道你什么时候可以ENDstream.php的一个实例?

我的天真印象是,如果是这样的话,PHP 不是适合这种服务器的技术。但是到目前为止我看到的所有演示都暗示 PHP 对此很好,这就是为什么我很困惑...

最佳答案

"...does "stream.php" stay open as long as the client is "connected" to it?"

是的,你的伪代码是一种合理的方法。

"And how do you know when you can END an instance of stream.php?"

在最典型的情况下,这发生在用户离开您的网站时。 (Apache 识别出关闭的套接字,并杀死 PHP 实例。)您可能从服务器端关闭套接字的主要时间是如果您知道一段时间内将没有数据;您发送给客户的最后一条消息是告诉他们在某个时间回来。例如。在您的股票流媒体案例中,您可以在晚上 8 点关闭连接,并告诉客户在 8 小时内回来(假设纳斯达克从早上 4 点到晚上 8 点开放报价)。星期五晚上你告诉他们星期一早上回来。 (我有一本即将出版的关于 SSE 的书,并专门讨论了这个主题。)

"...if this is the case, PHP isn't a suitable technology for this kind of server. But all of the demos I've seen so far imply that PHP is just fine for this, which is why I'm so confused..."

嗯,人们认为 PHP 不是一种适合普通网站的技术,他们是对的:如果用 C++ 替换整个 LAMP 堆栈,则可以用更少的内存和 CPU 周期来完成它。然而,尽管如此,PHP 为大多数网站提供了良好的支持。它是一种非常高效的 Web 工作语言,因为它结合了熟悉的类 C 语法和许多库,并且对于管理人员来说是一种安慰,因为有大量的 PHP 程序员可以雇用,大量的书籍和其他资源,以及一些大型的用例(例如 Facebook 和 Wikipedia)。这些基本上与您可能选择 PHP 作为您的流技术的原因相同。

典型的设置不会是每个 PHP 实例与 NASDAQ 的一个连接。相反,您将有另一个进程与 NASDAQ 的单一连接,或者集群中的每台机器到 NASDAQ 的单一连接。然后将价格插入 SQL/NoSQL 服务器或共享内存。然后 PHP 只是轮询共享内存(或数据库),并将数据推出。或者,有一个数据收集服务器,每个 PHP 实例打开一个到该服务器的套接字连接。数据收集服务器在收到更新时将更新推送到其每个 PHP 客户端,然后它们又将这些数据推送到其客户端。

使用 Apache+PHP 进行流式传输的主要可扩展性问题是每个 Apache 进程的内存。当您达到硬件的内存限制时,做出业务决策,将另一台机器添加到集群中,或者将 Apache 排除在循环之外,并编写一个专用的 HTTP 服务器。后者可以在 PHP 中完成,因此您现有的所有知识和代码都可以重复使用,或者您可以用另一种语言重写整个应用程序。我这个纯粹的开发人员会用 C++ 编写一个专用的、流线型的 HTTP 服务器。我的经理会添加另一个盒子。

关于php - 服务器发送的事件和 php - 什么触发服务器上的事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14564903/

相关文章:

javascript - EventSource/SSE(服务器发送事件)- 安全

iis-7.5 - 如何为SSE(服务器发送事件)和SignalR配置IIS 7.5

php - 为什么我的SQL语句只返回一条记录?

php - mySQl,查询 : How to customize selection from database?

php - 我需要一个不同的 html 页面来打印吗?

go - 事件源golang : how to detect client disconnection?

javascript - 服务器发送的事件在脚本完成之前不会更新

ruby-on-rails - 为什么SSE在rails上卡在连接上?

php - 或者在带有子查询的 Laravel 查询生成器中的 WHERE IN

php - 使用 javascript 和 jquery 动态包含一个 php 文件