Skip to content

分布式架构概述

IM 系统采用插件化架构设计,通过配置切换存储层和消息路由层,实现从单实例到多实例分布式部署的无缝升级。

架构对比

特性免费版(单实例)收费版(分布式)
存储SQLite(本地文件)MySQL(共享数据库)
消息路由本地内存Redis Pub/Sub
最大用户数~100010000+
实例数1不限
负载均衡Go 网关
水平扩展不支持支持
依赖零依赖MySQL + Redis

架构拓扑

免费版

┌──────────────┐
│   客户端      │
└──────┬───────┘
       │ HTTP / WebSocket

┌──────────────────────────────────────┐
│         IM Server (Node.js)          │
│                                      │
│  ┌──────────┐  ┌──────────────────┐  │
│  │ REST API │  │ WebSocket Server │  │
│  └────┬─────┘  └────────┬─────────┘  │
│       │                 │            │
│  ┌────┴─────────────────┴─────────┐  │
│  │    SQLite (内存数据库)          │  │
│  └────────────────────────────────┘  │
└──────────────────────────────────────┘

收费版

                      ┌──────────────────┐
                      │    客户端集群      │
                      └────────┬─────────┘

                      ┌────────▼─────────┐
                      │   Go 网关 (网关)   │
                      │  负载均衡 + 路由   │
                      └────────┬─────────┘

            ┌──────────────────┼──────────────────┐
            ▼                  ▼                  ▼
   ┌────────────────┐ ┌────────────────┐ ┌────────────────┐
   │  IM Server #1  │ │  IM Server #2  │ │  IM Server #N  │
   │  (Node.js)     │ │  (Node.js)     │ │  (Node.js)     │
   └───────┬────────┘ └───────┬────────┘ └───────┬────────┘
           │                  │                  │
           └──────────────────┼──────────────────┘

                 ┌─────────────────────────┐
                 │    Redis Pub/Sub         │
                 │    跨实例消息广播         │
                 └────────────┬────────────┘

                 ┌─────────────────────────┐
                 │    MySQL                 │
                 │    共享持久化存储         │
                 └─────────────────────────┘

核心设计

插件化架构

系统通过两个抽象层实现存储和消息路由的可替换:

┌─────────────────────────────────────────────────┐
│              业务逻辑层 (不变)                     │
└────────────┬───────────────────────┬────────────┘
             │                       │
             ▼                       ▼
   ┌──────────────────┐   ┌──────────────────┐
   │   存储接口        │   │   消息路由接口    │
   │   Storage        │   │   Messenger      │
   └────────┬─────────┘   └────────┬─────────┘
            │                      │
       ┌────┴────┐            ┌────┴────┐
       │ 可选实现 │            │ 可选实现 │
       ├─────────┤            ├─────────┤
       │ SQLite  │ ← 免费版   │ Local   │ ← 免费版
       │ MySQL   │ ← 收费版   │ Redis   │ ← 收费版
       └─────────┘            └─────────┘

配置驱动

通过环境变量或配置文件切换运行模式:

bash
# 免费版 - 零依赖
./im-server

# 收费版 - 启用 MySQL + Redis
STORAGE=mysql MESSENGER=redis ./im-server

消息路由原理

单实例模式:WebSocket 连接直接保存在内存中,消息直接推送。

分布式模式:每个实例维护本地连接表,通过 Redis Pub/Sub 广播消息。当实例 A 需要给用户发消息时:

  1. 先检查本地连接表
  2. 如果用户在本实例,直接推送
  3. 如果不在,通过 Redis 广播给所有实例
  4. 持有该用户连接的实例收到广播后推送

代码结构

server/
├── index.js              # 主入口
├── db.js                 # SQLite 实现
├── config.js             # 统一配置
├── lib/
│   ├── storage/          # 存储层抽象
│   │   ├── index.js      # 工厂函数
│   │   ├── interface.js  # 接口定义
│   │   └── sqlite.js     # SQLite 实现
│   └── messenger/        # 消息路由层抽象
│       ├── index.js      # 工厂函数
│       ├── interface.js  # 接口定义
│       └── local.js      # 本地实现
├── plugins/              # Pro 版插件
│   ├── storage-mysql.js  # MySQL 存储插件
│   └── messenger-redis.js # Redis 消息路由插件
└── gateway/              # Go 网关
    ├── main.go
    ├── go.mod
    └── gateway.yaml

性能参考

指标免费版收费版 (10 实例)
最大并发连接~1000~10000
消息延迟< 10ms< 50ms
内存占用~100MB~200MB/实例
数据库 QPS~500~5000

选择建议

  • 1000 用户以内:免费版完全够用,零运维成本
  • 1000-10000 用户:收费版,2-5 个实例
  • 10000+ 用户:收费版 + 更多实例,或考虑替换存储层为 PostgreSQL