一台手机,同时发给平板、PC、笔记本三台设备。其中PC网络慢,会不会把另外两台也拖慢?这就是多设备并发要解决的问题。

文章封面

前五篇都是"一台设备发给另一台"。

这一篇升级成"一台设备同时发给多台"。

我之前做过一个测试:手机上会议资料,同时发给平板A、平板B、PC。

结果呢?PC网络特别慢,传了半天还没传完。平板A本来10秒就能完成,结果等了30秒。平板B更惨,直接超时失败了。

为什么?因为我把所有设备的任务放在一个队列里跑。PC那个任务卡住了,后面的任务全在等。

这就是多设备并发的坑:一台设备慢,不能影响其他设备。

一、每台设备一个独立Session

正确的做法是:每台目标设备,建一个独立的DeviceSession。

每个Session自己管:

  • 自己的任务队列
  • 自己的传输状态
  • 自己的重试次数
  • 自己的统计信息

A设备慢?没关系,它自己慢慢传。B设备正常跑自己的,不受影响。

多设备并发架构

二、DeviceSession:每台设备独立运行

这段代码解决什么问题: 单设备独立会话。
文件: session/DeviceSession.ets
用途: 管理单台设备的传输任务
接入位置: 多设备分发时创建

class DeviceSession {
  deviceId: string;
  deviceName: string;
  taskQueue: TransferTask[] = [];
  status: 'idle' | 'connecting' | 'transferring' | 'failed' | 'completed' = 'idle';
  successCount: number = 0;
  failCount: number = 0;
  retryCount: number = 0;
  
  constructor(deviceId: string, deviceName: string) {
    this.deviceId = deviceId;
    this.deviceName = deviceName;
  }
  
  // 添加任务
  addTask(task: TransferTask) {
    this.taskQueue.push(task);
  }
  
  // 处理任务
  async processTasks() {
    this.status = 'transferring';
    while (this.taskQueue.length > 0) {
      let task = this.taskQueue.shift()!;
      try {
        await this.sendOne(task);
        this.successCount++;
      } catch (e) {
        this.failCount++;
        console.warn('设备 ' + this.deviceName + ' 任务失败:' + e);
      }
    }
    this.status = 'completed';
  }
}

三、多Session调度:不要互相等

有了多个DeviceSession,怎么调度?

很简单:每个Session独立启动,不要互相等待。

手机同时给三台设备发资料,就是创建三个Session,每个Session独立跑自己的任务队列。

这段代码解决什么问题: 多设备并发调度。
文件: scheduler/MultiDeviceScheduler.ets
用途: 调度多设备并发传输
接入位置: 批量分发时调用

class MultiDeviceScheduler {
  private sessions: Map<string, DeviceSession> = new Map();
  
  // 创建多设备会话
  createSessions(devices: Array<{id: string, name: string}>) {
    for (let dev of devices) {
      let session = new DeviceSession(dev.id, dev.name);
      this.sessions.set(dev.id, session);
    }
  }
  
  // 给所有设备发任务
  broadcastTask(task: TransferTask) {
    for (let session of this.sessions.values()) {
      // 每个设备一个任务副本
      let taskCopy = {...task, id: task.id + '_' + session.deviceId};
      session.addTask(taskCopy);
    }
  }
  
  // 启动所有会话(并行)
  async startAll() {
    let promises = [];
    for (let session of this.sessions.values()) {
      promises.push(session.processTasks());
    }
    // 等所有完成,不互相阻塞
    await Promise.allSettled(promises);
    console.info('所有设备传输完成');
  }
}

四、多设备并发最容易踩的坑

第一个坑:所有设备共用一个队列。
一台设备慢,整个队列卡住,其他设备都在等。正确做法是每台设备独立队列。

第二个坑:一台失败全部取消。
PC传失败了,平板也跟着取消了。不对,单台失败不影响其他设备。

第三个坑:重复任务没去重。
用户点了两次"全部分发",结果每台设备收到两份相同的任务。要做任务幂等性判断。

第四个坑:内存峰值没控制。
三台设备同时传大文件,每台都读进内存,内存直接涨三倍。要控制每台设备的并发数。

第五个坑:失败重试不隔离。
PC网络不好,一直重试,占着CPU和网络,影响其他设备。重试要限制次数和间隔。

第六个坑:没有性能统计。
哪台设备慢?慢在哪?传了多少?成功率多少?没有统计就是黑盒。

多设备传输状态

传输统计页面


第六篇总结:

多设备并发的核心是"隔离"。每台设备一个独立Session,自己的任务队列、自己的状态、自己的重试。一台设备慢或失败,不影响其他设备。

工程上最容易翻车的是把所有设备的任务放一个队列里,一台卡住全部卡死。分开以后,用Promise.allSettled并行跑,谁慢谁自己等,不拖别人。

下一篇做工程收尾:异常恢复、状态机、资源释放。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐