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 万线程,OS 直接崩溃。Netty 的 Reactor 模型用少量 I/O 线程处理所有连接。
- NIO:BIO(阻塞 I/O)的
accept()和read()会阻塞线程。NIO 的 Selector 可以同时监控成千上万个连接。 - 序列化:JSON 文本协议相比 Netty 的 Protobuf 效率低很多。
可扩展方向
如果要做一个生产可用的 IM 系统,发展方向:
- Netty 替代原生 Socket:Reactor 线程模型
- WebSocket 替代 TCP:浏览器兼容
- gRPC 替代 JSON:强类型、双向流、Protobuf
- 分布式架构:多个 IM Server 节点 + 消息路由
但无论选哪个方向,协议设计、心跳、粘包处理、并发控制 这些底层问题始终需要面对。