HTTP/2无客户端可用API而WebSockets提供的含义及示例咨询
相关核心观点:
- HTTP/2虽然支持服务端向浏览器推送二进制数据,但该能力未对浏览器端JS暴露,因此音视频帧推送这类场景仍需使用WebSockets。
- HTTP/2推送本质是浏览器与服务端之间的交互,而WebSockets真正暴露了可供客户端(浏览器中运行的JavaScript)和服务端应用代码调用的API,用于传输实时数据。
“推送的二进制数据未对浏览器JS暴露”的具体含义
简单说就是:HTTP/2推送到浏览器的二进制数据,你写的页面JavaScript完全拿不到实时控制权,甚至感知不到推送行为的发生。
举个最常见的例子:
你访问一个普通网页,HTML里引用了1个JS文件、1个CSS文件、1张首屏大图。没有HTTP/2推送的时候,浏览器要先请求拿到HTML,解析到这三个资源的标签,再依次发三个请求拉取资源,多了三次网络往返的开销。
开了HTTP/2推送之后,服务器返回HTML响应的同时,会主动把这三个关联资源的二进制内容一起推给浏览器。浏览器内核收到这些推送数据后,会直接扔进本地HTTP缓存里,等后面解析HTML发现需要这三个资源的时候,直接从缓存读,不用再发网络请求。
整个过程里,推过来的JS、CSS、图片的二进制数据,全程由浏览器内核的网络模块、缓存模块接管,页面里的JS既不会在数据到达的时候收到任何通知,也拿不到原始的数据流做自定义处理。
这也是为什么音视频帧推送这类场景用不了HTTP/2:实时音视频要求服务器每推一帧编码后的画面数据,JS能立刻拿到这帧二进制,马上喂给解码器渲染到画面上。但HTTP/2推的数据只会进缓存,你根本没法在数据到达的瞬间触发回调拿数据,总不能为了每一帧画面生成一个唯一URL,再反复发请求从缓存里读吧?不管是延迟还是性能开销都完全不可用。
“HTTP/2 push是浏览器和服务器之间的交互”的含义,以及WebSocket API的实际所指
这句话的核心意思是:HTTP/2推送的参与方只有服务器、浏览器内核两个角色,整个逻辑是底层网络层面的优化,和你写的前后端业务代码无关。
还是拿静态资源推送举例:你要开HTTP/2推送,一般是在Nginx、Caddy这种Web服务器的配置文件里写规则,比如“访问首页的时候自动推JS和CSS文件”,这个规则和你后端写的业务接口、业务逻辑完全没关系;浏览器端收到推送的时候,也是内核自己处理缓存,根本不会通知页面上的JS。说白了这就是浏览器和Web服务器之间约定好的、用来加快页面加载速度的内置机制,你写的上层应用既没法自定义推送什么内容,也没法干预推送的处理流程,甚至很多时候你都不知道当前页面有没有用到HTTP/2推送。
而WebSocket(包括socket.io这类封装库)提供的客户端可调用API,是真的把双向通信的完整控制权开放给了业务代码:
浏览器给JS暴露了原生的WebSocket构造函数,你写几行代码就能完全掌控整个通信过程:
// 前端业务代码 const liveWs = new WebSocket('wss://你的服务地址/live'); // 连接建立成功时会立刻触发这个回调 liveWs.onopen = () => { console.log('实时连接已建立'); }; // 服务器每推一条消息/一帧二进制数据过来,会立刻触发这个回调 // 你可以直接拿到原始数据做任意自定义处理 liveWs.onmessage = (event) => { const pushData = event.data; // 如果是音视频帧就解码渲染,如果是聊天消息就插入页面,如果是协同数据就更新画布 processCustomData(pushData); }; // 你要给服务器发数据,直接调用send方法就行,什么时候发、发什么内容完全由你控制 liveWs.send(JSON.stringify({ type: 'danmaku', content: '主播好强' }));
后端也是一样,不管你用什么语言写WebSocket服务,业务代码都能拿到连接实例,在任意时机给指定客户端推送自定义格式的数据,收到客户端消息也能立刻触发回调处理。
socket.io这类库只是在原生WebSocket基础上做了自动重连、心跳保活、低版本降级、房间广播这些封装,核心还是把实时通信的控制权完全交给了前后端的应用代码,这就是所谓“提供客户端可调用API”的实际含义。
核心差异总结
- HTTP/2推送是浏览器内核和Web服务器之间的底层加载优化,设计目标是减少静态资源加载的网络开销,上层业务代码无感知、无控制权,没法用来传输自定义实时数据。
- WebSocket是专门为双向实时通信设计的协议,从标准层面就给前后端业务代码暴露了完整的操作接口,收发数据的时机、格式、处理逻辑完全由业务代码自定义,适合实时音视频、聊天、协同编辑这类场景。
内容的提问来源于stack exchange,提问作者Aquarius_Girl

