Skip to content

架构设计 ​

了解NapLink的内部架构和设计理念。

架构概览 ​

┌─────────────────────────────────────┐
│          NapLink (主类)              │
│          extends EventEmitter        │
└─────────────────────────────────────┘
           │
           ├── ConnectionManager  (连接管理)
           │   ├── ReconnectService  (重连服务)
           │   └── HeartbeatService  (心跳服务)
           │
           ├── ApiClient  (API调用)
           │
           └── EventRouter  (事件路由)

核心组件 ​

1. ConnectionManager ​

负责WebSocket连接的完整生命周期管理。

职责:

  • WebSocket 连接/断开
  • 连接超时控制
  • 状态管理
  • 错误处理

状态机:

DISCONNECTED → CONNECTING → CONNECTED
              ↓              ↓
              ← RECONNECTING ←

2. ReconnectService ​

实现指数退避重连策略。

算法:

delay = min(initial * multiplier^attempt, max)

示例:

尝试1: 1秒后
尝试2: 2秒后
尝试3: 4秒后
尝试4: 8秒后
...
最多: 60秒

3. HeartbeatService ​

定期发送心跳保持连接活跃。

机制:

  • 定时发送ping
  • 检测pong响应
  • 连续超时触发重连

4. ApiClient ​

管理所有API请求和响应。

特性:

  • 请求/响应匹配(通过echo)
  • 超时控制
  • 自动重试
  • 内存清理

5. EventRouter ​

解析和分发OneBot事件。

流程:

原始消息 → 解析 → 路由 → 触发事件
                  ↓
              层级化事件树

设计原则 ​

1. 单一职责 ​

每个类只负责一件事:

  • ConnectionManager只管连接
  • ApiClient只管API
  • EventRouter只管事件

2. 依赖注入 ​

所有依赖通过构造函数注入:

typescript
constructor(
  private connection: ConnectionManager,
  private config: NapLinkConfig,
  private logger: Logger
) {}

3. 事件驱动 ​

使用EventEmitter模式:

typescript
client.emit('connect');
client.on('connect', handler);

4. 类型安全 ​

完整的TypeScript类型:

typescript
async call<T extends keyof WSSendParam>(
  method: T,
  params: WSSendParam[T]
): Promise&lt;WSSendReturn[T]&gt;

核心流程 ​

连接流程 ​

1. 用户调用 connect()
2. ConnectionManager 创建 WebSocket
3. 设置超时定时器
4. 监听 onopen 事件
5. 启动心跳服务
6. 触发 'connect' 事件

消息接收流程 ​

1. WebSocket 收到消息
2. 解析 JSON
3. 检查是否有 echo(API响应)
   - 有:交给 ApiClient 处理
   - 无:交给 EventRouter 路由
4. EventRouter 解析事件类型
5. 触发层级化事件

API调用流程 ​

1. 用户调用 API 方法
2. 生成唯一 echo
3. 创建 Promise
4. 设置超时定时器
5. 发送请求
6. 等待响应
7. 匹配 echo
8. resolve/reject Promise

性能优化 ​

1. 内存管理 ​

定期清理过期的待处理请求:

typescript
setInterval(() => {
  const now = Date.now();
  for (const [id, req] of this.pendingRequests) {
    if (now - req.createdAt > timeout * 2) {
      this.pendingRequests.delete(id);
    }
  }
}, 60000);

2. 事件优化 ​

使用Map存储事件处理器,O(1)查找。

3. 私有字段 ​

使用#私有字段而非private,真正的私有化。

扩展性 ​

自定义Logger ​

typescript
interface Logger {
  debug(message: string, ...meta: any[]): void;
  // ...
}

自定义配置 ​

所有配置都有默认值,支持部分覆盖。

与其他SDK的区别 ​

查看 对比分析 了解详情。

Released under the MIT License.