Bun.serve() 支持服务器端 WebSockets,具备实时压缩、TLS 支持以及 Bun 原生的发布-订阅 API。
⚡️ 吞吐量提升 7 倍Bun 的 WebSockets 速度很快。在 Linux x64 上运行的简单聊天室中,Bun 每秒处理的消息数是 Node.js +
"ws" 的 7 倍。Bun 内部的 WebSocket 实现基于 uWebSockets。
启动 WebSocket 服务器
以下服务器使用Bun.serve 构建,会在 fetch 处理程序中将每个传入请求升级为 WebSocket 连接。你可以在 websocket 参数中声明套接字处理程序。
server.ts
server.ts
为速度设计的 API
为速度设计的 API
在 Bun 中,你只需为每个服务器声明一次处理程序,而不是为每个套接字分别声明。你可以将单个
WebSocketHandler 对象传递给 Bun.serve(),其中包含 open、message、close、drain 和 error 方法。这种设计不同于客户端的 WebSocket 类,后者扩展了 EventTarget(onmessage、onopen、onclose)。客户端通常只会打开少量套接字连接,因此基于事件的 API 在客户端很适用。但服务器端往往会打开 大量 连接,这意味着:- 为每个连接添加/移除事件监听器所花费的时间会累积起来
- 为每个连接存储回调函数引用会占用额外内存
- 通常,人们会为每个连接创建新函数,这同样意味着更多的内存开销
ServerWebSocket 实例。ServerWebSocket 类是一个快速的、原生 Bun 实现的 WebSocket,并提供了一些额外功能。
server.ts
发送消息
每个ServerWebSocket 实例都有 .send() 方法用于向客户端发送消息,支持多种输入类型。
server.ts
头信息
升级成功后,Bun 会根据规范发送101 Switching Protocols 响应。要为此 Response 附加额外的 headers,请将它们传递给 server.upgrade()。
server.ts
上下文数据
在.upgrade() 调用中为新的 WebSocket 附加上下文 data。它可在 WebSocket 处理程序中的 ws.data 属性上访问。
要为 ws.data 进行强类型定义,可在 websocket 处理对象里添加 data 属性,从而为所有生命周期钩子中的 ws.data 指定类型。
server.ts
以前,你可以像
Bun.serve<MyData>({...}) 这样通过 Bun.serve 上的类型参数指定 ws.data 的类型。由于 TypeScript 的一项限制,Bun 移除了这种写法,改用 data 属性。WebSocket。
browser.js
用户身份识别浏览器会将页面上设置的 Cookie 与 WebSocket 升级请求一同发送。它们可在
fetch 处理程序中的 req.headers 上获取。解析这些 Cookie 以识别连接的用户,并据此设置 data。发布/订阅
Bun 的ServerWebSocket 包含用于基于主题进行广播的原生发布-订阅 API。你可以使用字符串标识符指定主题。单个套接字可以通过 .subscribe() 订阅主题,并通过 .publish() 向该主题的所有其他订阅者发送消息(不包括自身)。这种基于主题的广播 API 类似于 MQTT 和 Redis Pub/Sub。
server.ts
.publish(topic, data) 会向主题的所有订阅者发送消息,_但不包括_调用 .publish() 的套接字。要向主题的所有订阅者发送消息,请使用 Server 实例上的 .publish() 方法。
压缩
使用perMessageDeflate 参数启用逐消息压缩。
server.ts
boolean 作为第二个参数传递给 .send()。
背压管理
ServerWebSocket 的 .send(message) 方法返回一个 number 表示操作结果。
-1— 消息已入队,但存在背压(backpressure)0— 由于连接问题,消息已丢弃1+— 发送的字节数
超时和限制
默认情况下,Bun 会关闭处于空闲状态超过 120 秒的 WebSocket 连接。使用idleTimeout 参数进行配置。
maxPayloadLength 参数进行配置。
连接到 WebSocket 服务器
Bun 实现了WebSocket 类。创建连接至 ws:// 或 wss:// 服务器的 WebSocket 客户端实例,类似于浏览器中的用法。
WebSocket API 的标准特性。
在 Bun 中,你还可以直接在构造函数中设置自定义请求头。这是 Bun 对 WebSocket 标准的特有扩展。在浏览器中无法使用。
背压管理
浏览器的WebSocket API 无法减慢发送速度超过你处理速度的对端:传入的消息会无限制地缓存在内存中。Bun 添加了 pause() 和 resume(),用于暂停和恢复从底层套接字读取数据,从而让发送方感受到 TCP 背压。这是 Bun 特有的扩展。在浏览器中无法使用。
pause() 和 resume() 在操作生效时(或连接中的套接字打开后生效时)返回 true,没有可操作的套接字时则返回 false;socket.isPaused 用于报告当前状态。调用 pause() 时已经解码的消息仍可能被传递。ws 包中的 pause()、resume() 和 isPaused 对应相同的方法。
参考
See Typescript Definitions