IM即时通讯系统设计——TIO 作为技术框架
在IM即时通讯的技术调研中,对比了业务几个开源,半开源的的技术框架。例如野火(收费的),jim(社区版免费,商业版收费)等等,最终选择tio作为核心组件。tio主要完成的工作。
1. 高性能网络通信(TCP/UDP)
-
封装了 Java NIO,让开发者不用直接操作 Selector、Channel 等底层类。如果不用tio,为了支持即时通讯这种大量的网络链接,通讯数据小而且并发高的业务特点,开发人员需要自己设计多线程,基于NIO的功能。这就涉及很复杂的线程间通讯,线程维护,网络资源开启回收等等。包括后续的测试,优化等工作。借助tio,开发人员可以把时间精力更专注与具体业务功能的开发。
2. 轻松构建高并发服务端
-
TIO自己的官网https://www.tiocloud.com/tio/docs/t-io/start/de . 测评数据是支持百万级别的链接
- 0-10万连接。内存变化较大。主要是由于内存初始化时jvm会占用一部分内存。
- 10万之后。每增加10万连接 内存占用率上升300M左右。
- 随着连接数增加可以发现cpu性能对连接数影响不大。
- 新生代内存与老生代内存占用率比较合理。
- 并发30W连接在2小时内。内存变化不明显。处于合理状态
根据以上数据可以推论 —-> 以8G内存(可使用内存为7.5G左右)为例:当内存占用率达到5G左右时足以支撑100W并发连接。todo t-io能够支持那么高并发的原理是什么。
-
但是我们自己的项目压力测试只给到一万的网络链接,十万的QPS。完全没有问题。
-
客户端状态管理(在线状态、心跳等)。这个模块没有用tio。是自己实现的。
t-io可以用较小内存,支持百万链接的原理:
1. 底层采用 NIO + 单线程 Reactor 模型
t-io
底层基于 Java NIO 构建,但封装得非常简洁:
-
使用 一个主线程 Acceptor 接收连接;
-
使用 多个 Reactor 线程 负责 I/O 读写;
-
每个 Reactor 线程对应一个
Selector
,每次处理一批连接; -
所有连接都基于 非阻塞 IO,并且复用线程和内核资源。少量线程管理大量连接,极大减少了线程上下文切换开销。
2. 每个连接几乎不分配额外线程
不像传统的“一连接一线程”:
传统模型 | t-io |
---|---|
每个连接 1 个线程(上万线程容易 OOM) | 所有连接共享少量线程 |
线程上下文切换频繁 | 事件驱动,极少切换 |
调度器负担重 | 几个 SelectorThread 轻松搞定 |
3. 内存复用 + 零拷贝机制(ByteBuffer 池)
t-io
会:
-
复用
ByteBuffer
,避免频繁申请/释放内存; -
解码失败时不拷贝完整数据,而是记录位置,下一次继续解;
-
避免 GC 压力,提升吞吐。
4. 业务处理与 IO 分离(HandlerRunnable + DecodeRunnable)
t-io
把网络通信流程拆分为多个阶段,每个阶段分配不同线程池处理:
阶段 | 线程角色 | 优点 |
---|---|---|
解码 | DecodeRunnable | 防止粘包拆包阻塞网络线程 |
业务处理 | HandlerRunnable | 可配置并发数处理业务 |
编码发送 | SendRunnable | 可异步发送大消息,不阻塞 |
这样做的好处:
-
网络线程专注收发;
-
解码和业务在不同线程中执行,不会阻塞收消息;
-
吞吐量更高,更适合高并发。
以上这些机制,让它在百万连接下内存消耗更低。
3. 自动粘包拆包
-
TCP 是字节流协议,没有消息边界。因此
-
t-io 内部维护了每个连接的接收缓冲区 ByteBuffer;自己定义“怎么识别一条完整消息” ⇒ 实现
getPacketLength
收到完整消息后怎么处理 实现decode
-
t-io 内部维护了每个连接的接收缓冲区 ByteBuffer;每次收到数据,都会调用你的
getPacketLength()
;如果当前 buffer 里数据长度 ≥ 返回的长度:就截取这一段字节,交给你的decode()
方法解码;如果不够(拆包),就等下次数据到达;如果超过(粘包),就会继续切下一条消息。getPacketLength 举例如下,但是实际中的getPacketLength方法不是这样,带补充
@Override
public int getPacketLength(ByteBuffer buffer, int limit) {if (limit < 4) return -1; // 不够判断长度int bodyLength = buffer.getInt(); // 前4字节表示消息体长度return 4 + bodyLength; // 总长度 = 长度字段 + 消息体
}
5. 支持分布式集群
-
内置
tio-cluster
支持多节点之间的广播通信。基于Redis 集群广播、集群同步 session 信息等
6. 便于构建即时通信(IM)系统
-
官方有完整 IM 框架:tio-im
-
内置用户绑定、群聊、点对点消息等能力。 todo带补充详细,为什么tio可以方便的支持群聊,绑定。以及如果不用tio,会怎么样。