怎么用 Netty 实现 WebSocket 服务?WebSocket 和 HTTP 是什么关系?
简化版
Netty 内置了对 HTTP 和 WebSocket 的支持,能方便地实现 WebSocket 服务(实时双向通信,如聊天、推送、在线协作)。理解要点:① WebSocket 和 HTTP 的关系——WebSocket 连接是「从 HTTP 升级来的」:客户端先发一个带 Upgrade: websocket 头的 HTTP 请求(握手),服务端同意后「升级」成 WebSocket 连接,之后就用 WebSocket 协议做全双工双向通信(不再是 HTTP 的请求-响应);② Netty 实现 WebSocket 的 pipeline——需要几个现成的 Handler:HttpServerCodec(HTTP 编解码,处理握手阶段的 HTTP)、HttpObjectAggregator(把 HTTP 消息聚合完整)、WebSocketServerProtocolHandler(处理 WebSocket 握手和协议升级,指定路径如 /ws),之后加自己的业务 Handler 处理 TextWebSocketFrame(文本帧)/BinaryWebSocketFrame(二进制帧)。核心:WebSocket 从 HTTP 升级而来,用于全双工实时通信;Netty 用 HttpServerCodec + HttpObjectAggregator + WebSocketServerProtocolHandler 处理握手升级,业务 Handler 处理 WebSocket 帧。
详细版
WebSocket vs HTTP:
| 维度 | HTTP | WebSocket |
|---|---|---|
| 通信模式 | 请求-响应(半双工) | 全双工(双向、随时推送) |
| 连接 | 短连接(一般) | 长连接(一直保持) |
| 服务端主动推送 | 不能(要轮询) | 能(随时推送给客户端) |
| 建立方式 | 直接请求 | 从 HTTP 升级(握手) |
| 头部开销 | 每次请求带完整头 | 握手后帧头很小 |
| 适用 | 请求-响应式交互 | 实时双向(聊天、推送、协作) |
// Netty WebSocket 服务端 pipeline
ch.pipeline()
.addLast(new HttpServerCodec()) // HTTP 编解码(握手阶段)
.addLast(new HttpObjectAggregator(65536)) // 聚合 HTTP 消息(握手请求完整)
.addLast(new WebSocketServerProtocolHandler("/ws")) // 处理 WS 握手升级,路径 /ws
.addLast(new MyWebSocketHandler()); // 业务:处理 WebSocket 帧
// 业务 Handler:处理 WebSocket 帧
public class MyWebSocketHandler
extends SimpleChannelInboundHandler<TextWebSocketFrame> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
String text = frame.text(); // 收到文本消息
// 处理、回复
ctx.writeAndFlush(new TextWebSocketFrame("回复: " + text));
// 广播给所有连接:channelGroup.writeAndFlush(new TextWebSocketFrame(...))
}
}
WebSocket 握手(从 HTTP 升级):
客户端 → HTTP 请求:GET /ws Upgrade: websocket Connection: Upgrade ...
服务端 → 101 Switching Protocols(同意升级)
→ 之后连接变成 WebSocket,全双工通信(TextWebSocketFrame/BinaryWebSocketFrame)
⚠️ 理解 WebSocket 的关键,是「它从 HTTP 升级而来,但升级后就不是 HTTP 了」——这解释了 Netty pipeline 为什么要那几个 Handler。握手阶段是 HTTP:客户端发一个特殊的 HTTP GET 请求(带
Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Key等头),所以 pipeline 需要HttpServerCodec(处理这个 HTTP 请求)和HttpObjectAggregator(把 HTTP 请求聚合完整,因为握手请求可能分片)。WebSocketServerProtocolHandler负责「升级」:它拦截握手请求、验证、回复101 Switching Protocols,完成后把连接「切换」成 WebSocket 模式,并在 pipeline 里动态调整(握手后 HTTP 相关的 Handler 就不用了)。升级后是 WebSocket:数据以「帧(Frame)」传输——TextWebSocketFrame(文本)、BinaryWebSocketFrame(二进制)、PingWebSocketFrame/PongWebSocketFrame(心跳)、CloseWebSocketFrame(关闭);你的业务 Handler 处理这些帧。所以 WebSocket = 「HTTP 握手升级 + 之后的全双工帧通信」,Netty 的那几个 Handler 正好对应「处理握手的 HTTP + 完成升级 + 处理 WebSocket 帧」。
完整版教学
一、WebSocket 是什么:全双工实时通信
先理解 WebSocket 解决的问题:
HTTP 的局限(对实时通信):
HTTP 是"请求-响应"模式——客户端请求、服务端响应
→ 服务端不能主动推送给客户端(只能等客户端来问)
→ 实时场景(聊天、推送、股价、在线协作)怎么办?
轮询(客户端不停地问"有新消息吗")→ 浪费、延迟
长轮询(服务端 hold 住请求直到有数据)→ 有改善但仍别扭
WebSocket 的方案:全双工双向通信
建立一个长连接,客户端和服务端可以"随时互相发消息"
→ 服务端能主动推送给客户端(不用客户端问)
→ 全双工(双向、同时)、低延迟、长连接
适用场景:
① 实时聊天/IM
② 消息推送(服务端主动推)
③ 实时数据(股价、监控、游戏)
④ 在线协作(文档协同编辑)
→ 需要"服务端主动推 + 双向实时"的场景
所以 WebSocket = 全双工的长连接,用于实时双向通信
解决了 HTTP 不能主动推送的问题
WebSocket 解决 HTTP 的局限——HTTP 是请求-响应模式,服务端不能主动推送(实时场景要轮询/长轮询,浪费、延迟)。WebSocket 的方案:全双工双向通信——建立长连接,客户端服务端随时互相发消息、服务端能主动推送、全双工低延迟长连接。适用:实时聊天/IM、消息推送、实时数据(股价/监控/游戏)、在线协作。理解「HTTP 请求-响应服务端不能主动推(实时要轮询浪费);WebSocket 全双工长连接(随时互发/服务端主动推/双向实时);适用聊天/推送/实时数据/协作」,就理解了 WebSocket 的定位。
二、WebSocket 和 HTTP 的关系:升级
理解 WebSocket 从 HTTP「升级」而来:
WebSocket 连接的建立——从 HTTP 升级:
① 客户端发一个"特殊的 HTTP GET 请求"(握手请求):
GET /ws HTTP/1.1
Upgrade: websocket ← 请求升级到 WebSocket
Connection: Upgrade
Sec-WebSocket-Key: xxx ← 握手密钥
Sec-WebSocket-Version: 13
② 服务端同意升级,回复:
HTTP/1.1 101 Switching Protocols ← 101 状态码=切换协议
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: yyy ← 用 Key 算出的应答
③ 握手完成 → 连接"升级"成 WebSocket
→ 之后不再是 HTTP,用 WebSocket 协议通信(帧)
为什么要从 HTTP 升级:
① 复用 HTTP 的基础设施(端口 80/443、经过防火墙/代理)
② 兼容——先用 HTTP 握手,服务端不支持就是普通 HTTP
→ WebSocket 借 HTTP 完成"协商",然后升级
握手后的变化:
握手前:HTTP(请求-响应)
握手后:WebSocket(全双工帧通信)
→ 同一个 TCP 连接,协议从 HTTP 变成 WebSocket
所以 WebSocket = HTTP 握手升级 + 之后的 WebSocket 通信
WebSocket 从 HTTP「升级」而来:① 客户端发特殊 HTTP GET 请求(握手,带 Upgrade: websocket/Connection: Upgrade/Sec-WebSocket-Key)→ ② 服务端回 101 Switching Protocols(同意升级,带 Sec-WebSocket-Accept)→ ③ 握手完成、连接升级成 WebSocket(之后用帧通信不再是 HTTP)。为什么从 HTTP 升级:复用 HTTP 基础设施(端口/防火墙/代理)、兼容(先 HTTP 握手)。握手前是 HTTP、握手后是 WebSocket(同一 TCP 连接协议变了)。理解「WebSocket 从 HTTP 升级:客户端发握手请求(Upgrade:websocket)→服务端回 101 Switching Protocols→升级成 WebSocket(之后帧通信);为什么:复用 HTTP 基础设施+兼容;握手前 HTTP 握手后 WebSocket」,就理解了 WebSocket 和 HTTP 的关系。
三、Netty 的 WebSocket pipeline
理解 Netty 实现 WebSocket 需要的 Handler:
Netty WebSocket 服务端 pipeline(对应握手+升级+帧处理):
① HttpServerCodec:
HTTP 编解码器(HttpRequestDecoder + HttpResponseEncoder)
→ 处理握手阶段的 HTTP 请求/响应
(握手请求是 HTTP,要用它解析)
② HttpObjectAggregator:
把 HTTP 消息的多个部分(请求行、头、体)聚合成一个完整的 FullHttpRequest
→ 握手请求可能分片,聚合完整才好处理
参数是最大内容长度
③ WebSocketServerProtocolHandler("/ws"):
★ 核心——处理 WebSocket 握手和协议升级
- 拦截 /ws 路径的握手请求
- 验证握手、回复 101、完成升级
- 升级后处理 Ping/Pong 心跳、Close 帧等控制帧
- 动态调整 pipeline(握手后移除 HTTP 相关的、加 WebSocket 帧编解码)
④ 你的业务 Handler:
处理 WebSocket 数据帧(TextWebSocketFrame / BinaryWebSocketFrame)
每个 Handler 的职责对应 WebSocket 的两个阶段:
握手阶段(HTTP):HttpServerCodec + HttpObjectAggregator
升级:WebSocketServerProtocolHandler
帧通信(WebSocket):业务 Handler
所以 Netty WebSocket pipeline = HTTP 编解码 + 聚合 + 协议升级 + 业务帧处理
Netty WebSocket 服务端 pipeline(对应握手+升级+帧处理):① HttpServerCodec(HTTP 编解码,处理握手阶段的 HTTP)、② HttpObjectAggregator(聚合 HTTP 消息成完整 FullHttpRequest,握手请求可能分片)、③ WebSocketServerProtocolHandler("/ws")(核心——处理 WebSocket 握手和升级:拦截握手请求、验证、回 101、完成升级、处理 Ping/Pong/Close 控制帧、动态调整 pipeline)、④ 业务 Handler(处理 TextWebSocketFrame/BinaryWebSocketFrame 数据帧)。每个 Handler 对应 WebSocket 阶段:握手(HTTP)→ 升级 → 帧通信。理解「Netty WebSocket pipeline:HttpServerCodec(HTTP 编解码握手)+HttpObjectAggregator(聚合完整)+WebSocketServerProtocolHandler(核心处理握手升级/控制帧/动态调整 pipeline)+业务 Handler(处理数据帧);对应握手 HTTP→升级→帧通信」,就掌握了 Netty 的 WebSocket pipeline。
四、WebSocket 帧类型
理解 WebSocket 的「帧(Frame)」——升级后的数据单位:
WebSocket 升级后,数据以"帧(Frame)"传输:
数据帧:
TextWebSocketFrame:文本帧(UTF-8 文本,如 JSON 消息)
frame.text() 拿到文本
BinaryWebSocketFrame:二进制帧(字节数据,如文件、Protobuf)
frame.content() 拿到 ByteBuf
控制帧:
PingWebSocketFrame / PongWebSocketFrame:心跳(Ping 发、Pong 回)
→ 保持连接活跃、检测连接
CloseWebSocketFrame:关闭帧(协商关闭连接)
ContinuationWebSocketFrame:分片续帧(大消息分多帧)
业务 Handler 处理数据帧:
extends SimpleChannelInboundHandler<TextWebSocketFrame>
channelRead0(ctx, TextWebSocketFrame frame) {
String text = frame.text();
// 处理文本消息
ctx.writeAndFlush(new TextWebSocketFrame(回复));
}
控制帧的处理:
WebSocketServerProtocolHandler 通常帮你处理 Ping/Pong/Close
→ 业务 Handler 主要处理数据帧(Text/Binary)
广播(群发):
用 ChannelGroup 管理所有连接
channelGroup.writeAndFlush(new TextWebSocketFrame(消息))
→ 群发给所有 WebSocket 连接(聊天室场景)
所以 WebSocket 数据以帧传输(Text/Binary 数据帧 + Ping/Pong/Close 控制帧)
WebSocket 升级后数据以「帧(Frame)」传输:数据帧(TextWebSocketFrame 文本帧 frame.text()、BinaryWebSocketFrame 二进制帧 frame.content())、控制帧(PingWebSocketFrame/PongWebSocketFrame 心跳、CloseWebSocketFrame 关闭、ContinuationWebSocketFrame 分片续帧)。业务 Handler 处理数据帧(SimpleChannelInboundHandler<TextWebSocketFrame>)。控制帧通常 WebSocketServerProtocolHandler 帮处理。广播用 ChannelGroup(channelGroup.writeAndFlush(帧) 群发,聊天室场景)。理解「WebSocket 数据以帧传输:数据帧(TextWebSocketFrame 文本 frame.text/BinaryWebSocketFrame 二进制)+控制帧(Ping/Pong 心跳/Close 关闭);业务 Handler 处理数据帧、控制帧 WebSocketServerProtocolHandler 帮处理;广播用 ChannelGroup 群发」,就掌握了 WebSocket 帧类型。
五、心跳与连接管理
WebSocket 长连接要注意心跳和连接管理:
心跳(保持连接活跃、检测死连接):
WebSocket 是长连接,要保持活跃、检测断开
① 协议层心跳:Ping/Pong 帧
一端发 PingWebSocketFrame,另一端回 PongWebSocketFrame
→ WebSocketServerProtocolHandler 可自动回 Pong
② 应用层心跳 + IdleStateHandler:
用 IdleStateHandler 检测"一段时间没数据"
→ 触发 IdleStateEvent → 发心跳 或 关闭空闲连接
(见 heartbeat-idle-state 题)
连接管理(多连接):
用 ChannelGroup 管理所有活跃的 WebSocket 连接
channelActive 时加入、channelInactive 时移除
→ 广播、统计在线数、按用户找连接
背压(推送太快):
服务端主动推送时,如果推太快、客户端接收慢
→ 写缓冲堆积 → 用水位线 + isWritable 背压(见 write-backpressure 题)
安全(WSS):
WebSocket 也可以走 TLS(wss:// 而非 ws://)
→ pipeline 加 SslHandler(HTTPS/WSS)
所以 WebSocket 长连接要:心跳(Ping/Pong+IdleStateHandler)、
连接管理(ChannelGroup)、背压、安全(WSS)
WebSocket 长连接要注意:① 心跳(保持活跃、检测死连接)——协议层 Ping/Pong 帧(WebSocketServerProtocolHandler 可自动回 Pong)、应用层 IdleStateHandler(检测空闲、发心跳或关闭空闲连接);② 连接管理——ChannelGroup 管理所有连接(channelActive 加入、channelInactive 移除、广播/统计在线);③ 背压(推送太快用水位线+isWritable);④ 安全(WSS,pipeline 加 SslHandler)。理解「WebSocket 长连接注意:心跳(Ping/Pong+IdleStateHandler 检测空闲)、连接管理(ChannelGroup 广播/统计在线)、背压(推太快用水位线)、安全(WSS 加 SslHandler)」,就掌握了心跳与连接管理。
六、实践与总结
总结 Netty 实现 WebSocket 的实践:
实现步骤:
① pipeline 配置(握手+升级+帧处理):
HttpServerCodec + HttpObjectAggregator
+ WebSocketServerProtocolHandler(路径)
+ 业务 Handler
② 业务 Handler 处理 TextWebSocketFrame/BinaryWebSocketFrame
③ 连接管理用 ChannelGroup(广播、在线管理)
④ 心跳(IdleStateHandler + Ping/Pong)
⑤ 需要 TLS 加 SslHandler(wss)
实践建议:
① WebSocketServerProtocolHandler 处理握手升级和控制帧
② 业务 Handler 用 SimpleChannelInboundHandler<TextWebSocketFrame>(自动 release)
③ ChannelGroup 管理连接(广播、统计)
④ 心跳保活 + 检测死连接
⑤ 推送注意背压(isWritable)
WebSocket vs HTTP 的选择:
请求-响应式交互 → HTTP
实时双向、服务端推送 → WebSocket(聊天、推送、协作)
核心总结:
WebSocket 从 HTTP 升级、全双工实时通信
Netty pipeline: HttpServerCodec + HttpObjectAggregator
+ WebSocketServerProtocolHandler + 业务 Handler
数据以帧传输(Text/Binary 数据帧 + Ping/Pong/Close 控制帧)
长连接注意心跳、连接管理、背压
Netty 实现 WebSocket 步骤:① pipeline 配置(HttpServerCodec+HttpObjectAggregator+WebSocketServerProtocolHandler(路径)+业务 Handler)、② 业务 Handler 处理数据帧、③ ChannelGroup 连接管理、④ 心跳(IdleStateHandler+Ping/Pong)、⑤ TLS 加 SslHandler(wss)。实践:WebSocketServerProtocolHandler 处理握手升级、业务 Handler 用 SimpleChannelInboundHandler<TextWebSocketFrame>、ChannelGroup 管理连接、心跳保活、推送注意背压。理解「实现步骤:pipeline 配置(HTTP 编解码+聚合+协议升级+业务)+处理数据帧+ChannelGroup 连接管理+心跳+TLS;实践:WebSocketServerProtocolHandler 处理升级/业务用 SimpleChannelInboundHandler/ChannelGroup 广播/心跳保活/背压」,就掌握了 Netty 实现 WebSocket 的实践。
记忆钩子:「Netty 实现 WebSocket(实时双向通信:聊天/推送/协作);★WebSocket 从 HTTP 升级:客户端发握手请求(Upgrade:websocket)→服务端回 101 Switching Protocols→升级成 WebSocket(之后全双工帧通信不再是 HTTP);Netty pipeline:①HttpServerCodec(HTTP 编解码握手阶段)②HttpObjectAggregator(聚合 HTTP 完整)③WebSocketServerProtocolHandler(路径,核心-处理握手升级/控制帧/动态调整 pipeline)④业务 Handler(处理 TextWebSocketFrame/BinaryWebSocketFrame 数据帧);数据以帧传输:数据帧(Text/Binary)+控制帧(Ping/Pong 心跳/Close 关闭);长连接注意:心跳(IdleStateHandler+Ping/Pong)、连接管理(ChannelGroup 广播/在线)、背压(推太快 isWritable)、安全(WSS 加 SslHandler)」。
七、常见误区与追问
- 误区:WebSocket 和 HTTP 完全无关。 WebSocket 是从 HTTP 升级来的——客户端先发一个带 Upgrade: websocket 头的 HTTP GET 请求(握手),服务端回 101 Switching Protocols 同意升级,之后同一个 TCP 连接的协议从 HTTP 变成 WebSocket;这也是为什么 Netty 的 WebSocket pipeline 需要 HttpServerCodec(处理握手阶段的 HTTP)。
- 误区:WebSocket 升级后还是 HTTP 的请求-响应。 升级后不是 HTTP 了——WebSocket 是全双工的:客户端和服务端可以随时互相发消息,服务端能主动推送给客户端(不用客户端请求),数据以「帧」传输(TextWebSocketFrame 等),不再是 HTTP 的请求-响应模式。
- 误区:Netty 实现 WebSocket 只要一个 Handler。 需要几个:HttpServerCodec(处理握手的 HTTP)、HttpObjectAggregator(聚合 HTTP 消息完整)、WebSocketServerProtocolHandler(处理握手升级和控制帧)、业务 Handler(处理数据帧);因为 WebSocket 有握手(HTTP)和帧通信(WebSocket)两个阶段,要不同的 Handler 处理。
- 误区:WebSocket 长连接不用管心跳。 要管——WebSocket 是长连接,要保持活跃、检测死连接;用协议层的 Ping/Pong 帧(WebSocketServerProtocolHandler 可自动回 Pong)和应用层的 IdleStateHandler(检测一段时间没数据、发心跳或关闭空闲连接);否则死连接会一直占着资源。
- 追问:WebSocket 和 HTTP 是什么关系? WebSocket 连接是从 HTTP 升级来的——客户端先发一个特殊的 HTTP GET 请求(握手请求,带 Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Key 等头),服务端同意后回复 101 Switching Protocols(切换协议),完成后同一个 TCP 连接就从 HTTP「升级」成 WebSocket,之后用 WebSocket 协议做全双工双向通信(不再是 HTTP 的请求-响应);从 HTTP 升级是为了复用 HTTP 的基础设施(端口、防火墙、代理)和兼容性。
- 追问:Netty 实现 WebSocket 服务端的 pipeline 怎么配置? 需要:① HttpServerCodec(HTTP 编解码器,处理握手阶段的 HTTP 请求响应);② HttpObjectAggregator(把 HTTP 消息聚合成完整的 FullHttpRequest,因为握手请求可能分片);③ WebSocketServerProtocolHandler(指定 WebSocket 路径如 /ws,负责处理握手、验证、回复 101 完成协议升级,还处理 Ping/Pong/Close 控制帧、握手后动态调整 pipeline);④ 你的业务 Handler(处理 TextWebSocketFrame、BinaryWebSocketFrame 数据帧);对应握手(HTTP)→升级→帧通信三个阶段。
- 追问:WebSocket 有哪些帧类型? 数据帧:TextWebSocketFrame(文本帧,UTF-8 文本如 JSON)、BinaryWebSocketFrame(二进制帧,字节数据如文件、Protobuf);控制帧:PingWebSocketFrame/PongWebSocketFrame(心跳,Ping 发、Pong 回,保持连接活跃)、CloseWebSocketFrame(关闭帧,协商关闭连接)、ContinuationWebSocketFrame(分片续帧,大消息分多帧);业务 Handler 主要处理数据帧(Text/Binary),控制帧通常由 WebSocketServerProtocolHandler 处理。
八、加强记忆
Netty 内置对 HTTP 和 WebSocket 的支持,能方便地实现 WebSocket 服务(实时双向通信:聊天、推送、在线协作)。WebSocket 和 HTTP 的关系:WebSocket 从 HTTP「升级」而来——客户端先发带 Upgrade: websocket 头的 HTTP GET 请求(握手),服务端回 101 Switching Protocols 同意升级,之后同一 TCP 连接从 HTTP 升级成 WebSocket,做全双工双向通信(服务端能主动推送、不再是请求-响应);从 HTTP 升级是为复用 HTTP 基础设施和兼容。Netty 的 WebSocket pipeline:① HttpServerCodec(HTTP 编解码,处理握手阶段)、② HttpObjectAggregator(聚合 HTTP 消息完整)、③ WebSocketServerProtocolHandler("/ws")(核心——处理握手升级、控制帧、动态调整 pipeline)、④ 业务 Handler(处理数据帧)——对应「握手(HTTP)→升级→帧通信」三阶段。升级后数据以「帧」传输:数据帧(TextWebSocketFrame 文本、BinaryWebSocketFrame 二进制)、控制帧(PingWebSocketFrame/PongWebSocketFrame 心跳、CloseWebSocketFrame 关闭)。长连接注意:心跳(IdleStateHandler + Ping/Pong)、连接管理(ChannelGroup 广播/在线)、背压(推送太快用 isWritable)、安全(WSS 加 SslHandler)。一句话「WebSocket 从 HTTP 升级(握手请求 Upgrade:websocket→101 Switching Protocols→全双工帧通信);Netty pipeline:HttpServerCodec(握手 HTTP)+HttpObjectAggregator(聚合)+WebSocketServerProtocolHandler(处理握手升级/控制帧)+业务 Handler(处理数据帧);数据以帧传输(Text/Binary 数据帧+Ping/Pong/Close 控制帧);长连接注意心跳/连接管理 ChannelGroup/背压/WSS」。