HTML5数据推送SSE原理及应用开发
在Web开发中,JavaScript用于实现页面的交互行为,CSS负责页面的外观呈现,而HTML则兼具表达页面逻辑结构和承载数据内容的功能。通常在更新数据时,往往只需更新数据本身,而无需改变页面的结构。正是这种仅更新数据而不改变组织结构的需求,催生了数据拉取和数据推送技术。
一、SSE概述
SSE(Server-Sent Events)是一种基于HTML5的技术,允许服务器端主动向客户端推送新数据。在探讨SSE之前,我们先了解一下数据推送的两种替代方案:无更新方案和数据拉取方案。
(一)无更新方案
当用户加载HTML页面后,浏览器会自动请求页面所需的图片、CSS文件和JavaScript文件等,这些文件通常是可以被浏览器缓存的静态文件。若页面使用后端语言(如PHP、Ruby和Python等)为用户动态生成HTML,同样遵循此流程。在这种方案中,一旦页面加载完成,除非用户手动刷新页面,否则页面数据不会更新。
(二)数据拉取方案
浏览器会根据用户的某些行为、经过一定时间或者基于其他触发机制,向服务器端请求更新部分或全部数据。可以通过JavaScript或meta标签来命令整个页面重新加载。我们熟知的Ajax技术常用于请求最新数据,当接收到数据后,JavaScript函数会利用这些数据局部更新DOM。数据拉取的核心原则是:仅拉取新数据,并且只更新页面中受影响的部分。
需要明确的是,上述两种方案都不属于数据推送。数据推送既不是静态文件的加载,也不依赖于浏览器为更新数据而主动发起的请求,而是由服务器主动选择向客户端发送新数据。当数据源有新数据产生时,服务器端能够立即将这些数据发送给一个或多个客户端,无需等待客户端的请求。这些新数据可以是突发新闻、最新股票行情、上线朋友的聊天信息、新的天气预报、策略游戏中的下一步行动等。
二、SSE的特点及与WebSocket的比较
SSE适用于数据更新频繁、对延迟要求较低且数据流向仅从服务端到客户端的场景。它与WebSocket有以下区别:
(一)SSE的优势
- 使用便利:无需添加任何新组件,开发者可以继续使用熟悉的后端语言和框架,无需为新建虚拟机配置新的IP或端口号。
- 服务器端简洁:SSE基于现有的HTTP/HTTPS协议运行,能够直接利用现有的代理服务器和认证技术。
(二)与WebSocket的对比
WebSocket相较于SSE的最大优势在于它支持双向通信,即服务器发送数据和接收数据同样便捷。而SSE一般需要通过一个独立的Ajax请求从客户端向服务端传送数据,这会增加额外的开销。因此,如果需要以每秒一次或者更快的频率向服务端传输数据,建议使用WebSocket。
三、SSE代码示例
(一)HTML代码
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>basic SSE test</title>
</head>
<body>
<pre id="x">initializting...</pre>
<!-- 使用pre标签确保数据能以原始格式呈现,不被修改或格式化 -->
</body>
<script>
var es = new EventSource("basic_sse.php");
es.addEventListener("message", function(e) {
// e.data
document.getElementById("x").innerHTML += "\n" + e.data;
}, false);
// 使用false表示在冒泡阶段处理事件,而非捕获阶段
</script>
</html>
(二)PHP代码
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
需要注意的是,Content-Type: text/event-stream 是专门为SSE设计的MIME类型。在使用服务器端数据之前,最好进行检查,以防潜在的JavaScript注入攻击。
四、效果截图
(此处可插入SSE应用的效果截图)
五、何时数据推送不是合适的选择
在考虑是否使用数据推送时,我们先分析静态情况。在不引入数据推送的情况下,每当用户打开一个页面,浏览器和服务器之间会建立一个套接字连接。服务器收集信息并返回给用户,这个过程可能简单到只是从磁盘加载一个静态HTML文件或一张图片,也可能复杂到需要运行一段连接多个数据库的后台语言代码。关键在于,一旦服务器返回了所需信息,套接字连接就会关闭。每个HTTP请求都会打开一个生命周期相对较短的套接字连接,这些套接字是服务器上的有限资源,使用完毕后会被循环再利用。
对比来看,数据推送的一个请求永远不会完成,服务器总是有新信息要发送,因此套接字会一直保持打开状态。显然,由于套接字是有限资源,同一时刻的SSE连接数会受到限制。
我们可以通过一个形象的例子来理解。假设你为一个应用提供电话服务支持,有10个接线中心员工为1000个用户服务。在传统模式下,用户遇到问题,接线员接听并解决问题后挂线,新的客户呼叫会排队等待。这类似于传统的HTTP请求模式。但如果有一个客户表示现在没有问题,但接下来几个小时都会使用产品,并且希望遇到问题时能立即得到回复,那么这个客户会与接线员保持通话几个小时,这就占用了10%的服务资源。如果有10个这样的客户,其他990个客户就无法呼叫。这就是数据推送模式可能带来的问题。
然而,数据推送并非总是不合适的。如果这个客户在一下午每隔几秒钟就有一个问题,保持电话通畅不仅不会浪费资源,反而会提高效率。因为如果每次问题都需要重新打电话(类似于数据拉取),接线员需要花费额外的时间验证客户身份、调出账户信息,这会降低服务效率。所以,保持电话通畅既让客户更满意,也提高了呼叫中心的工作效率,这就是数据推送最适合的场景。
综上所述,在选择是否使用数据推送时,需要综合考虑数据更新频率、延迟要求、资源占用等因素,以确保选择最适合的方案。