Skip to content

Netty 实战入门

这一章不追求复杂协议,而是站在“博客项目可能怎么用 Netty”的角度,讲清楚落地思路。

博客项目为什么会用到 Netty

最常见的几个方向:

  1. WebSocket 在线聊天。
  2. 实时通知推送。
  3. 管理后台消息提醒。
  4. 长连接在线状态管理。

一个实时通知系统的大致结构

mermaid
flowchart TD
    A["业务系统<br/>文章评论 / 点赞 / 私信"] --> B["通知服务<br/>生成通知事件"]
    B --> C["Netty 或 WebSocket 服务<br/>维护长连接"]
    C --> D["在线用户连接<br/>userId -> Channel"]
    D --> E["浏览器实时收到消息"]

核心原理

实时通知的本质不是“接口更快”,而是服务端能够主动找到用户的长连接并写入消息。传统 HTTP 请求通常是客户端主动拉取,服务端不能随时把新消息推给浏览器;Netty/WebSocket 维护长连接后,服务端就可以在业务事件发生时主动推送。

mermaid
flowchart TD
    A["用户登录"] --> B["建立 WebSocket / TCP 长连接"]
    B --> C["鉴权通过后绑定 userId 和 Channel"]
    C --> D["业务系统产生通知事件"]
    D --> E{"用户是否在线"}
    E -- "在线" --> F["找到 Channel 并推送"]
    E -- "离线" --> G["保存离线消息"]
    F --> H["客户端确认或展示"]
    G --> I["用户下次上线后拉取"]

如果不理解这条链路,很容易把实时通知做成“前端每几秒轮询一次接口”。轮询简单但有明显代价:请求量高、消息不够实时、用户越多数据库压力越大。长连接也不是没有成本,它需要处理鉴权、心跳、断线清理、多节点路由和消息可靠性。

一个典型开发步骤

  1. 启动 Netty 服务端。
  2. 配置 BossGroup 和 WorkerGroup。
  3. 初始化 ChannelPipeline。
  4. 处理连接事件。
  5. 处理消息收发。
  6. 维护用户连接关系。
  7. 做心跳和断线清理。

典型消息流转

mermaid
sequenceDiagram
    participant U as 用户浏览器
    participant N as Netty服务
    participant B as 博客业务服务

    U->>N: 建立长连接
    B->>N: 某文章收到新评论
    N->>N: 找到文章作者在线连接
    N-->>U: 推送评论通知

本章小结

Netty 对博客项目最现实的价值,不是替代所有接口开发,而是承担“实时通信能力”。

如果你的博客后续想做:

  1. 实时通知。
  2. 聊天。
  3. 在线状态。

那么 Netty 会是一个非常值得深入的方向。

常见风险和设计取舍

问题为什么会发生处理方式
用户刷新页面后旧连接还在旧 Channel 没有及时触发清理channelInactive 中解绑,并定期校验连接活跃状态
多节点部署找不到用户连接用户连接分散在不同 Netty 节点使用 Redis 记录 userId 到节点的映射,或让消息先进入 MQ
客户端假在线网络断开但服务端暂时没感知增加心跳和读空闲检测
消息丢失推送时连接断开或写失败重要通知先落库,再推送,客户端可补拉
推送太快导致堆积客户端消费慢或网络差做限流、批量、丢弃低价值消息或断开异常连接

代码 Demo:维护用户连接

java
public class OnlineChannelManager {
    private static final Map<Long, Channel> USER_CHANNELS = new ConcurrentHashMap<>();

    public static void bind(Long userId, Channel channel) {
        USER_CHANNELS.put(userId, channel);
    }

    public static void unbind(Long userId) {
        USER_CHANNELS.remove(userId);
    }

    public static void push(Long userId, String message) {
        Channel channel = USER_CHANNELS.get(userId);
        if (channel == null || !channel.isActive()) {
            return;
        }
        channel.writeAndFlush(message);
    }
}

业务系统产生通知后,可以调用:

java
OnlineChannelManager.push(authorId, "你的文章收到了新评论");

真实项目中还要处理多节点连接分布、用户鉴权、心跳检测、消息确认和离线消息。