# Titanium:自定义即时通讯的可扩展后端核心——从原型到生产
开发自定义即时通讯应用时,许多开发者会从 XMPP/ejabberd 或 Matrix/Synapse 入手。这些平台提供了现成的传输层、联邦机制和端到端加密。但要适配现代用户体验时,往往会遇到瓶颈。
基于 Erlang 的 XMPP/ejabberd 体积小巧、抗负载能力强,但存在以下问题:
- XML 消息体带来解析开销。
- MUC 群组无法线性扩展:参与者增多时 CPU 负载激增。
- 部分 XEP 扩展实现会导致业务逻辑中的竞态条件。
Matrix 功能强大,但其分层架构让修改变得复杂:Python 实现的 Synapse 在实时任务中受 GIL 限制。
混合架构——如用 ejabberd 处理传输 + FastAPI 负责 API/OTP/反应——会导致状态分裂、XML↔JSON 转换和额外队列。单一真相源在组件间变得模糊。
要点: 从零构建后端,能实现对状态和性能的完全掌控,更为简洁。
Titanium v1:FastAPI 负载测试
首个 Titanium 版本基于 FastAPI + WebSocket,实现核心功能:聊天、UIN、媒体、pts 同步。原型在 1000 用户场景下承受 500 RPS,消息 120 条/秒,媒体 40 条/分钟,断线率 7%。
RPS 测试覆盖完整路径:发送 → 投递 → 确认 → 同步。具体包括:
- 访问权限校验。
- pts 更新(消息点,用于增量同步)。
- 实时 WebSocket 推送。
- 网络不稳时的重试。
- 离线客户端的更新日志。
规模化时暴露问题:
- GIL 限制 WebSocket 并发。
- PostgreSQL 在 pts 表高争用时锁表。
- 媒体存储需临时链接,而非永久。
Titanium 架构:真相源头
Titanium 定义了严格的状态管理规则:
- 服务器即真相源: 绝不信任客户端,所有变更走 API。
- Pts 机制: 类似 Telegram 的消息点增量同步。
- 更新日志: 不可变日志,用于状态重放。
- 分布式状态: 按 UIN 分片,无粘性会话。
- 媒体: S3 风格临时签名,24 小时 TTL。
核心组件:
- 网关: WebSocket + HTTP/2,限流,JWT。
- 核心: 业务逻辑、pts、ACL(按 UIN/群组)。
- 存储: PostgreSQL(状态)+ Redis(会话/队列)+ S3(媒体)。
- 工作者: Celery/RQ 处理异步任务(媒体处理、机器人)。
Pts 同步示例(伪代码):
% 客户端请求增量更新
handle_get_updates(ReqPts) ->
Updates = db:fetch_updates_after(ReqPts, UserId),
NewPts = lists:max([U#update.pts || U <- Updates]),
{reply, #{updates => Updates, pts => NewPts}}.
转向 Erlang/OTP:可扩展性与韧性
Python 无法处理 10k 并发 WebSocket,Erlang/OTP 完美解决:
- Actor 模型:每个 UIN 对应一个监督树 + gen_server。
- VM 热重载,无宕机。
- 内置 Mnesia/ETS,低延迟存储。
- Cowboy 支持单节点 100 万+ WebSocket 连接。
基准测试:
| 场景 | FastAPI (Python) | Titanium (Erlang) |
|----------|-------------------|--------------------|
| 1k 用户,120 消息/秒 | 500 RPS | 5k RPS |
| 10k WS | 20% CPU | 5% CPU |
| 媒体 100/分钟 | 2s 延迟 | 200ms |
Gen_server 会话示例:
-module(session).
-export([start_link/1, handle_message/2]).
handle_call({send_message, Msg}, _From, State) ->
case validate_rights(Msg) of
ok ->
NewPts = State#state.pts + 1,
save_update(Msg#update{pts=NewPts}),
broadcast_to_peers(Msg),
{reply, ok, State#state{pts=NewPts}};
{error, Reason} -> {reply, {error, Reason}, State}
end.
群聊与边缘场景
群聊是难点。摒弃 MUC,转向:
- 分片房间: 领导者由 hash(UIN 列表) 决定,从节点复制增量。
- 在线状态: ETS 存储在线/离线,重新连接时 pubsub。
- 恶劣网络: 乐观发送 + 服务器确认,从日志补漏。
处理场景:
- 重复发送(msg_id 幂等性)。
- 数据包乱序(时间戳 + 序列号)。
- 休眠/唤醒标签页(长轮询 fallback)。
- 机器人 webhook 重试(死信队列)。
核心要点
- Titanium 不是 MTProto 克隆,而是一个精简实时栈:pts、日志、分片。
- Erlang/OTP 提供 10 倍 RPS,CPU 仅 Python 的 1/4。
- 服务器真相源避免客户端不一致。
- 媒体/机器人异步卸载,核心专注投递。
- 扩展:3 节点处理 50k 用户、1k 消息/秒,无需联邦。
— Editorial Team
暂无评论。