服务端 API v2
  • API 概览
  • 快速开始
  • 调用方式
  • 房间信令接口
  • 混流转码接口
  • 媒体服务接口
  • 媒体文件接口
  • 音视频流审核接口
  • 场景服务接口
  • 回调说明
  • 全局返回码
  • 使用 Postman 调试
  • 文档中心
  • 服务端 API v2
  • 回调说明
  • 流回调乱序解决方案

流回调乱序解决方案

更新时间:2024-04-02 11:08

1 操作场景

开发者短时间内频繁对流进行创建和关闭时,ZEGO 提供的流创建回调和流关闭回调不保证结果的时序与开发者执行的时序一致。

当开发者需要依赖流创建和流关闭回调维护本地流列表或进行混流时,回调时序与执行时序的不一致可能会导致部分业务出错。

比如,开发者对一条流的操作顺序为:

  1. 流创建
  2. 流关闭
  3. 流创建

经过回调服务,到达开发者服务器的顺序有可能变为:

  1. 流创建
  2. 流创建
  3. 流关闭

开发者根据回调的顺序更新本地流列表,这条流会被删除,实际上这条流仍然在进行正常推流。

2 操作步骤

为了解决上述回调乱序导致的问题,ZEGO 推荐开发者使用以下方案维护本地流列表。

本方案基于回调不丢失的情况解决乱序的问题。如果回调丢失,则无法解决。

2.1 关注回调关键参数

关注流创建回调和流删除回调的关键参数。

参数 描述
event 事件名称
stream_id 流 ID, 对应客户端 StreamID
stream_seq 服务器流列表变更的序号,每次流变更都会加 1

stream_seq 与房间相关,每个房间都拥有独立的 stream_seq。当房间被关闭(当房间最后一个人退出房间的时候房间就会关闭)的时候,stream_seq 就会被重置。

stream_sid 流 server ID, 流唯一标识,由 ZEGO 后台生成

2.2 维护本地流列表

根据 stream_id,以及对应的 stream_sid 和对应房间的 stream_seq,维护本地流列表。

本地流列表的数据结构如下:

RoomStreamInfo: {
    StreamList: [
        {stream_id_1, stream_sid_1}, 
        {stream_id_2, stream_sid_2}
    ]
    StreamSeq: stream_seq
}

2.3 处理判断逻辑

收到回调后,处理流事件回调逻辑,更新本地流列表。

示例中的字段说明如下:

字段前缀 含义
zego_* ZEGO 回调中的参数
local_* 开发者本地维护的参数
  • 流创建回调

对比 stream_seq,当 zego_stream_seq > local_stream_seq 时,允许创建流,加入本地的流列表。

流创建回调
var localStreamList = [];
var localStreamSeq = 0;
// 流新增时
request("url", function(stream) {
    var streamSeq = stream["strean_seq"];
    var streamSid = stream["stream_sid"];
    if (streamSeq > localStreamSeq) { 
        // 当ZEGO服务器seq大于本地seq时才添加到本地的流列表
        localStreamList.add(stream);
    }
})
  • 流删除回调

对比 stream_seq 和 stream_sid,当 zego_stream_seq > local_stream_seqzego_stream_sid == local_stream_sid 时,允许删除流,更新本地的流列表。

流删除回调
var localStreamList = [];
var localStreamSeq = 0;
// 流删除时
request("url", function(stream) {
    var streamSeq = stream["strean_seq"];
    var streamSid = stream["stream_sid"];
    var localStream = localStreamList.find("stream_id")
    if (streamSeq > localStreamSeq && stramSid==localStream.localStreamSid) {
        // 当ZEGO服务器seq大于本地seq且为删除的流时才更新本地的流列表
        localStreamList.delete(localStream)
    }
})
本篇目录