什么触发了服务器上的事件?
所有,
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函数有什么不同?
对不起 - 这可能是一个令人难以置信的天真的问题。 但是我找不到的例子清楚地表明了这一点。
[UPDATE]
我认为我的问题措辞不佳,所以这里有一些澄清。
假设我有一个应该显示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
线程,因为您拥有并发用户? 如果是这样 - 是远程可行还是合适的方式来构建应用程序? 你怎么知道你什么时候可以结束一个stream.php
的实例?
我的天真印象是,如果是这种情况,PHP 不适合这种服务器。 但是迄今为止我看到的所有演示都暗示PHP对此很好,这就是为什么我很困惑......
服务器发送的事件用于从服务器端到客户端的实时更新。 在第一个示例中,不保留来自服务器的连接,并且客户端每3秒尝试连接一次,并使服务器发送的事件与ajax轮询无差别。
因此,为了保持连接,您需要将代码封装在一个循环中并不断检查更新。
PHP是基于线程的,更多的连接用户将使服务器资源耗尽。 这可以通过控制脚本执行时间并在脚本超过一定时间(即10分钟)时结束脚本来解决。 EventSource
API将自动再次连接,以便延迟处于可接受的范围内。
另外,请查看我的PHP库以了解服务器发送的事件,您可以更多地了解如何在PHP中执行服务器发送的事件并使代码更易于使用。
“...只要客户端与其”连接“,”stream.php“就保持打开状态?”
是的,你的伪代码是一个合理的方法。
“你怎么知道什么时候可以结束stream.php的一个实例?”
在最典型的情况下,这发生在用户离开您的网站时。 (Apache会识别封闭的套接字,并杀死PHP实例。)如果您知道一段时间内没有数据,那么您可能会从服务器端关闭套接字的主要时间; 你发给客户的最后一条消息是告诉他们在某个特定时间回来。 例如,在股票流动的情况下,您可以在晚上8点关闭连接,并告诉客户8小时后回来(假设纳斯达克的报价从早上4点到晚上8点)。 星期五晚上,你告诉他们星期一早上回来。 (我有一本关于上交所的即将出版的书,并在这个主题上专门写了几节。)
“......如果是这样的话,PHP并不适合这种服务器,但我所见过的所有演示都意味着PHP对此很好,这就是我为什么这么做的原因困惑...”
好吧,人们争辩说PHP对于普通网站来说不是一种合适的技术,而且他们是正确的:如果用C ++替换整个LAMP堆栈,则可以用更少的内存和CPU周期来实现。 但是,尽管如此,PHP为大多数网站提供了很好的支持。 由于熟悉的类C语法和许多图书馆的结合,这对于Web工作来说是一种非常高效的语言,对于经理来说,让大量PHP程序员雇用,大量书籍和其他资源以及一些大型用例(例如Facebook和维基百科)。 这些基本上与您选择PHP作为流式技术的原因基本相同。
典型的设置不会是每个PHP实例与NASDAQ的连接。 相反,您将拥有与NASDAQ建立单一连接的另一个流程,或者从集群中的每台计算机到纳斯达克的单个连接。 然后将价格推入SQL / NoSQL服务器或共享内存。 然后PHP只是轮询该共享内存(或数据库),并将数据推出。 或者,有一个数据收集服务器,每个PHP实例打开一个到该服务器的套接字连接。 数据收集服务器在每个PHP客户端收到更新时推送更新,然后将数据推送到客户端。
使用Apache + PHP进行流式传输的主要可扩展性问题是每个Apache进程的内存。 当达到硬件的内存限制时,请做出业务决定,将另一台机器添加到群集中,或将Apache从循环中删除,然后编写专用的HTTP服务器。 后者可以用PHP完成,这样所有现有的知识和代码都可以重新使用,或者可以用另一种语言重写整个应用程序。 我的纯开发人员会用C ++写一个专用的,精简的HTTP服务器。 我的经理会添加另一个盒子。
我注意到sse techink向客户端发送每一对延迟数据(例如像从Ajax池数据的客户端页面反转池数据techink),所以为了解决这个问题,我在sseServer.php页面中做了这个:
<?php
session_start();
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data
require 'sse.php';
if ($_POST['message'] != ""){
$_SESSION['message'] = $_POST['message'];
$_SESSION['serverTime'] = time();
}
sendMsg($_SESSION['serverTime'], $_SESSION['message'] );
?>
和sse.php是:
<?php
function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
?>
请注意,在sseSerer.php我开始一个会话并使用会话变量! 克服这个问题。
每当我想“更新”消息时,我也会通过Ajax调用sseServer.php(发布并设置variable message
值)。
现在在jQuery(javascript)我做这样的事情:1)我声明一个全局变量var timeStamp = 0; 第二)我使用下一个算法:
if(typeof(EventSource)!=="undefined"){
var source=new EventSource("sseServer.php");
source.onmessage=function(event)
if ((timeStamp!=event.lastEventId) && (timeStamp!=0)){
/* this is initialization */
timeStamp=event.lastEventId;
$.notify("Please refresh "+event.data, "info");
} else {
if (timeStamp==0){
timeStamp=event.lastEventId;
}
} /* fi */
} else {
document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
} /* fi */
在以下位置: $.notify("Please refresh "+event.data, "info");
有没有你可以处理的消息。
对于我的情况,我用来发送jQuery通知。
您可以使用POSIX PIPES或数据库表来通过POST传递“消息”,因为sseServer.php执行类似“无限循环”的操作。
我当时的问题是,上面的代码不会向所有客户端传递“消息”,而只会向这对客户端发送消息(称为sseServer.php的客户端以每个客户端的个人身份工作),所以我会将技术更改为从我想要触发“消息”的页面更新数据库,然后使用sseServer.php代替通过POST获取消息,从数据库表中获取消息。
我希望我有帮助!
链接地址: http://www.djcxy.com/p/57339.html