news 2026/5/21 2:57:02

WebRTC只管流不管控——自研信令服务器的状态机设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WebRTC只管流不管控——自研信令服务器的状态机设计

WebRTC 只管流,不管控——自研信令服务器的状态机设计

视频流是 WebRTC 的事。谁发起、谁接听、谁踢人、谁旁观——这些是信令的事。


一、问题

WebRTC 搞定了音视频传输。两个浏览器之间怎么建 PeerConnection、怎么传递 SDP、怎么走 ICE 打洞——这些都是现成的。

但一个视频帮办系统不只是"两个人能看见对方"。还需要:

  • 坐席发起通话,参保人接听
  • 坐席可以邀请第三方加入旁观
  • 坐席可以踢人
  • 多方加入时,每个人知道房间里有哪些人
  • 有人断线,其他人要知道
  • 通话结束后,知道是谁挂断的、挂了多久

这些 WebRTC 不管。得自己搭一层信令服务器


二、自研信令协议

设计一套轻量 JSON 信令。WebSocket 传输,每条消息一个类型:

信令方向说明谁来谁收
create坐席创建房间成功服务器坐席
joined有人加入房间后,给此人发的确认(带了所有在房间的人列表)服务器加入者
called有人申请加入,通知坐席是否允许服务器坐席
allow坐席允许加入坐席服务器
deny坐席拒绝加入坐席服务器
refused服务器通知申请者被拒绝服务器申请者
otherjoin有其他人加入房间(通知给已经在房间里的人)服务器其他人
bye有人主动离开离开者服务器
leaved有人离开,服务器通知房间里其他人服务器其他人
kick坐席踢人坐席服务器
kicked被踢的人收到通知服务器被踢者

关键设计决策:所有业务操作不走 P2P,全部经过信令服务器中转。坐席踢人不是直接发给参保人,是发给服务器 → 服务器发给被踢者 + 通知其他人。单一控制点,状态不会分叉。


三、房间状态机

一个房间的生命周期:

┌──────────┐ │ idle │ 等待坐席创建 └────┬─────┘ │ create ▼ ┌──────────┐ │ created │ 房间已建,等参保人加入 └────┬─────┘ │ join ▼ ┌──────────┐ │ joined │ 参保人已加入,等坐席允许 └────┬─────┘ │ allow ▼ ┌──────────┐ │ called │ 通话中(可能多人) └────┬─────┘ │ bye / kick / timeout ▼ ┌──────────┐ │ ended │ 所有人离开,房间销毁 └──────────┘

每个状态允许的操作不同:

状态允许的操作
created参保人加入、坐席取消
joined坐席允许/拒绝、第三方加入
called踢人、邀请第三方、正常挂断

状态机保护了异常路径——比如坐席在created状态还没人加入就发踢人指令,服务器直接拒绝,不会崩溃。


四、三种角色的加入和退出逻辑

坐席

  • 建房:发create→ 服务器创建房间,分配 roomId
  • 退出:发bye→ 服务器通知所有人leaved→ 房间销毁

参保人

  • 加入:发join(带 roomId)→ 服务器暂存 → 发called给坐席
  • 被允许:服务器发joined→ 参保人开始建 P2P 连接
  • 被拒绝:服务器发refused→ 参保人收到拒绝原因
  • 被踢:坐席发kick→ 服务器发kicked给参保人 → 通知其他人leaved

第三方(旁观)

  • 加入:同参保人,但坐席收到called时能看到是"旁观"角色
  • 退出:发bye或坐席踢,逻辑同参保人
  • 差别:不参与音视频流,只收到其他人的存在通知

五、一次完整通话的信令时序

以坐席 → 参保人一对一通话为例:

坐席 信令服务器 参保人 │ │ │ │──────── create ────────▶│ │ │◀───── create OK ────────│ │ │ │ │ ◀────── join ───────│ │◀───── called ───────────│ │ │ │ │──────── allow ──────────▶│ │ │◀───── allow OK ──────────│ │ │ │────── otherjoin ────────▶│ │ │ │ │════════════ WebRTC P2P 音视频流 ═══════════════════│ │ │ │ │ ◀─────── bye ───────│ │◀───── leaved ────────────│ │

Notes:

  1. 坐席建房后,房间处于created状态,等待参保人。
  2. 参保人 join 后,状态变为joined,坐席决定 allow 还是 deny。
  3. allow 后状态变为called,视频流开始。
  4. 参保人主动挂断(bye),服务器通知坐席(leaved),房间结束。
  5. 如果是坐席主动 bye,服务器直接销毁房间,通知所有人 leaved。

六、异常处理:断线、超时、重复加入

断线

WebSocket 断连时,服务器检测到连接关闭,等同于该用户主动 bye。处理逻辑:

  • 走正常离开流程,通知其他人leaved
  • 保留房间 N 分钟,等待重连
  • 超时没重连的人,从房间列表移除

超时

joined状态等待坐席 allow 超过 N 分钟 → 服务器自动给参保人发refused,房源回退到created

重复加入

同一个 roomId,同一个 userId 重复发 join → 服务器忽略,返回"已在房间中"。


七、总结

WebRTC 搞定了音视频流的传输。但它不负责:

  • 谁有权建房
  • 谁有权加入
  • 谁有权踢人
  • 旁观和发言有什么区别
  • 断线了怎么处理

这些是信令服务器的活。

这套自研协议只有 10 条左右信令,覆盖了远程帮办的全部业务场景。核心设计原则是:所有状态变更必须经过服务器——不是性能最优的方案,但状态一致性最高。政务场景不需要百万人并发,但绝对不能在通话中丢了状态。

信令层的代码不复杂。复杂的是想清楚"每个状态下谁可以做什么"。这个想清楚了,代码是自然推导出来的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 2:51:02

08-实战:RuoYi-Vue项目的自动化发布

服务器资源与角色 身份角色ip版本服务器Gitlab10.0.0.133Rocky Linux 9服务器Jenkins10.0.0.134Rocky Linux 9服务器Web10.0.0.135Rocky Linux 9服务器APP10.0.0.137Rocky Linux 9服务器Database10.0.0.138Rocky Linux 9服务器Harbor10.0.0.139Rocky Linux 9中间件Harbor-2.14…

作者头像 李华
网站建设 2026/5/21 2:47:12

购物小技巧:聪明消费,避免踩坑

人机协作,AI大模型:Deepseek仅供参考购物小技巧:聪明消费,避免踩坑在日常购物中,无论是线上还是线下,掌握一些实用的小技巧不仅能帮我们省钱,还能避免很多不必要的麻烦。很多人都有过这样的经历…

作者头像 李华
网站建设 2026/5/21 2:47:10

AI运动同时发布APP+小程序多端解决方案

引言:在开发AI运动健身应用时,您可能会遇到因为应用场景、用户群体覆盖等需求,需要发布APP小程序的多客户端的情况,今天就为您推荐一个APP小程序的多端AI运动应用解决方案。一、为什么要发布多端AI运动健身应用 根据插件已有的引用…

作者头像 李华