跳到正文
Joeplover
后端开发·2026-04-25·约 3 分钟阅读

Titan_IM:Java 即时通讯项目

基于 Java 开发的即时通讯后端项目,涉及 Netty、WebSocket、消息持久化、在线状态管理等核心技术。

即时通讯

Titan_IM:从零搭建 Java Socket 即时通讯

项目背景

Titan_IM 是一个基于原生 Java Socket 的简易即时通讯系统,目标是理解 IM 系统的底层原理——不做 Netty、WebSocket 这类高级抽象,直接从 TCP 长连接 + 多线程 + JSON 协议 开始。

为什么要从底层做起?因为不管用 Netty 还是 WebSocket,核心问题始终是:连接管理、消息协议、并发读写、粘包处理。理解了这些基础,上层框架只是 API 封装的不同。

架构设计

Client A ──┐
           ├── Server (Thread Pool) ── 消息队列 ── 分发线程 ── Client B
Client C ──┘

Server 层面:

  • 每个客户端连接分配一个独立线程处理
  • 接入消息队列(生产者-消费者模式)避免多线程同时写 Socket 导致乱序
  • 一个分发线程负责从队列取消息并转发给目标客户端

消息协议

定义 JSON 格式的消息体:

{
  "type": "chat",
  "from": "user_a",
  "to": "user_b",
  "content": "你好",
  "timestamp": 1700000000000,
  "msgId": "uuid-xxx"
}

消息类型覆盖:chat(私聊)、group(群聊)、system(系统通知)、heartbeat(心跳)。

粘包与半包处理

这是 TCP 编程的经典问题。TCP 是流式协议,不保证一次 read() 恰好读取到一条完整消息:

// 解决方案:在消息头前加 4 字节长度字段
// 格式:[4字节消息体长度][JSON消息体]
public void sendMessage(OutputStream out, String json) {
    byte[] data = json.getBytes(StandardCharsets.UTF_8);
    out.write(intToBytes(data.length));
    out.write(data);
    out.flush();
}

public String readMessage(InputStream in) {
    byte[] lenBytes = readExactly(in, 4);
    int len = bytesToInt(lenBytes);
    byte[] data = readExactly(in, len);
    return new String(data, StandardCharsets.UTF_8);
}

readExactly 是关键——它循环读取直到收满指定字节数,因为单次 read() 可能只收到部分数据。

心跳机制

客户端每隔 30 秒发送一个 {"type":"heartbeat"} 消息。Server 如果在 90 秒内没有收到客户端的任何消息,就判定连接断开,主动关闭 Socket 并清理资源。

// 服务端检测空闲连接
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(() -> {
    for (ClientConnection client : clients.values()) {
        if (System.currentTimeMillis() - client.lastHeartbeat > 90000) {
            client.close(); // 超时断开
        }
    }
}, 30, 30, TimeUnit.SECONDS);

与 Netty 的差距

原生 Socket 实现让我理解了 IM 的底层原理,但无法用于生产:

  1. 线程模型:一个连接一个线程 → 1 万连接需要 1 万线程,OS 直接崩溃。Netty 的 Reactor 模型用少量 I/O 线程处理所有连接。
  2. NIO:BIO(阻塞 I/O)的 accept() 和 read() 会阻塞线程。NIO 的 Selector 可以同时监控成千上万个连接。
  3. 序列化:JSON 文本协议相比 Netty 的 Protobuf 效率低很多。

可扩展方向

如果要做一个生产可用的 IM 系统,发展方向:

  • Netty 替代原生 Socket:Reactor 线程模型
  • WebSocket 替代 TCP:浏览器兼容
  • gRPC 替代 JSON:强类型、双向流、Protobuf
  • 分布式架构:多个 IM Server 节点 + 消息路由

但无论选哪个方向,协议设计、心跳、粘包处理、并发控制 这些底层问题始终需要面对。