浅谈云巴实时通信的编程模型

  概要

  有人常问,云巴实时通信系统到底提供了一种怎样的服务,与其他提供推送或 IM 服务的厂商有何本质区别。其实,从技术角度分析,云巴与其它同类厂商都是面向开发者的通信服务,宏观的编程模型都是大同小异,真正差异则聚焦于产品定位,业务模式,基础技术水平等诸多细节上。本文暂不讨论具体产品形态上的差异,着重从技术角度浅谈实时通信的编程模型。

  什么是实时通信

  「实时」(realtime) 一词在语义层面上隐含着对时间的约束(real-time constraint),在工程上,我们习惯对「需要在一定时间内」 完成的操作称为「实时操作」。通常,实时可细分为 「软实时」(soft realtime),「准实时」(firm realtime)和 「硬实时」(hard realtime)。它们之间的差异,简单来说,就是对无法在指定时间区间内(deadline)完成事务的容忍程度。维基百科上对这三者有如下 解释 :

  Hard – missing a deadline is a total system failure.

  Firm – infrequent deadline misses are tolerable, but may degrade the system's quality of service. The usefulness of a result is zero after its deadline.

  Soft – the usefulness of a result degrades after its deadline, thereby degrading the system's quality of service.

  假如我们把无法按时完成任务(missing a deadline)称为 异常事件 ,那么硬实时系统无法容忍异常事件;准实时系统则可容忍极少量的异常事件,但超过一定数量后系统可用性为 0;软实时系统可容忍异常事件,但是每发生一次异常事件,系统可用性降低。

  综上所述,我们可以举例:

  火星上的无人探测器是硬实时系统,因为一次异常事件就极有可能导致探测器不可用,同理可类推核电站的监控系统,军用无人机系统,远程导弹的导航系统等一系列军工产品;

  金融交易系统是准实时系统,此类系统可容忍极少数的交易故障,一旦故障次数增加,系统就会陷入崩溃状态;

  短信 / 手机推送 / 电商购物等都是软实时系统。对于此类系统,用户都可以容忍异常事件,但是太多的异常事件则会大幅降低系统可用程度,用户体验急剧下滑。

  就目前来说,绝大多数互联网产品(甚至可以说是 100%)都是软实时系统。 云巴实时通信系统的目标则是要做一个高可用的软实时系统 。

  一个最简单的实时通信编程模型

  在软件工程中,很多复杂的项目其实都可以用一个非常简洁的模型来概括。正如爱因斯坦所说的:「一切都应该尽可能地简单,但不要太简单」(Everything should be made as simple as possible, but not simpler)。虽然这是描述物理世界的经验之谈,但同样适用于计算机领域,将物理世界的关系投射到某种人为语言(物理公式/计算机编程语言),其规律其实都是共通的。

  让我们假设这么一个简单的场景: 对 10 个客户端发送一条消息 。

  这个需求其实可以用伪码表示为:

  for (i..10) {

  send_message(get_socket(i))

  }

  如果下图所示:

物联网

  在这个简单的需求下,我们只需要让这 10 个客户端分别跟服务器建立 TCP 连接(本文暂时只讨论 TCP 协议),然后遍历地发送消息即可。显而易见,这是一个O(N) 复杂度的逻辑。

  基于这个简单的模型,我们可以认为一条消息从发出到接收,有以下几个延时:

  网络延迟,一般是一个较为稳定的值,比如从北京到深圳,ping 延迟大约为 40 ms 左右;

  系统处理延迟,较之网络延迟,该值变化幅度较大,且可能因处理请求数的增加而急剧增大;

  云巴实时通信系统以 200 ms 延迟作为总延迟标准,也就是说,假如网络链路是从北京到深圳,除去网络延迟的 40 ms,要想达到 200 ms 的通信时间,系统延迟必须小于 160 ms。

  可以想象,当客户端数量达到一定数量级(比如百万级别)时,以上系统模型的实时性将面临极其严峻的考验。

  分而治之

  在海量用户下保持稳定的实时性,其实很多时候就只有一个手段: 分而治之 。

  图 1 表示的是单机处理情况。当单机的处理能力,带宽都无法应对客户端数量急剧增加的时候,我们就必须将线路进行分割。而且图 1 只体现了推送的意图(单向),但通信往往是一个双向的概念,综上,我们将 图 1 改成下面的 图 2 :