李亚飞——深圳至简天成科技有限公司创始人&CEO。12年全栈工程师,前深信服资深架构师,连续创业者,深圳Ruby社区发起人
▼
— 1 —
什么是实时协同的架构绘图?
首先看实时协同架构绘图技术的核心,我作为十多年的技术研发最大的体会是,任何技术最终都需要给商业价值提供非常核心的输出,所以我们来看一下架构的挑战。在分享之前,我先给大家播放一下视频,先感受一下成品。
这个是我们最终的成品,我们把云端绘制架构图,绘制流程图,绘制所有技术类相关的产品逻辑,都实现了双人在线上无缝丝滑的体验,整个过程我们大概花了一年的时间去迭代研发。
最大的核心价值点是在线上完成整个架构、交流、沟通、协作,是非常爽滑的感觉。具体我们可以看一下架构选型的核心方案:
首先,我们选择找这些点,最核心的是先找到一个起点,比如音视频的起点核心是找到 WebRTC,我们用的是 MxGraph,最基础的开源组件,在上面会做非常多的功能板块,核心特点是全部结构化构建底层数据,有自动的画布,整个导出可以做到全结构化的文档,如果 WebRTC 最好的方式是能够很容易扩展,能够以我们的业务需求扩展很多点,这一点就需要做的非常充分。
在整个过程中选择了非常多可能的技术架构、关于绘图板块的核心业务点,比如 jsPlumb、JointJS、QuneeJS,这个是商业帮助图形库的解决方案,这对整体社区资源,还有文档方面都比较有挑战,整体来说选择一个能够自我掌控、很好的去拓展的方案是比较有利的,尤其是在这些点上要掌握非常核心的技术优势。
— 2 —
协同算法
以上其实只是完成工作的10%,接下来另外一个核心话题就是:我们如何丝滑实现体验?
这里有两个核心算法给大家解释一下,第一个最常用的核心文档协作算法是 OT 算法,这个算法是90年伴随着谷歌的科学家开始打造的标准,之后因为这个技术有很大的挑战,到94年、95年才有一些文档系统实现出来,目前为止实时协同的数据,可能会存在丢一些点的问题,且 OT 算法有复杂的机制,以及排队的结构,这就要求前端也需要实现排队的算法。
核心理念就是把所有的操作转成三个操作,加、减和移动,把所有的东西都变成三个操作,通过数学公式,在服务端进行双向的处理,然后服务端再分发给各个端,这就是关于轻量级文档的技术。
这一块也是我们非常核心的算法,会应用在协同编程上,打造云端的编程环境。在这个板块里我们并不是直接选用这个技术,而是采用非常有点取巧,但是又非常酷的点,我们叫做 Diff/patch 算法,针对性的一个一个比对异同,再应用到每一个具体的节点上,调整完发送到另外一个端,AB两个用户之间就可以进行很好的同步。
这个是 Diff/patch 核心的算法实现,大家可以简单的过一下。首先拿到每一个对象,创建一个节点就会创建新的对象,跟对端对比,我们可以看到中间是不是多了?如果多了就会处理,如果有更新的操作,我们开始 Diff 出来然后形成一个 patch。核心的算法是这样不断的循环的,因为我们数的结构最大的优点是永远不会循环死锁。
Diff/patch 流程图
这个模式相比 OT 算法来说很容易掌控,它的延时和各个点非常扎实,唯一有一个挑战,但是我们在技术选型架构上需要考虑其中的点。偶尔会有网络丢失或者是一个状态可能会在过程中有非常低的机率,丢失一个小的图形,下一次更新的时候,或者有人动一下马上就会进入到最终的状态,这种点是万分之一,或者都不到万分之一来换取一个清晰的架构,这个事情我觉得是非常值的。
这个是代码的实现,大家简单过一下,核心接口是 CreatePatch,在每个节点上就会把加操作对对端是减操作,如果移动操作双方是一样的,通过这种方式进行配对,这边是整个算法核心,大家可以看看:
看起来非常简单,但是真正实现的时候可以想一下这个大前端的工程调试挑战或者难点就会非常大,这种技术可以应用于未来很多实际,构建一个云端实时互动的交互场景。
这个是最终的 Apply,反向应用的核心代码,核心代码是非常少的,就几个核心操作。
— 3 —
鼠标同步
当这个问题解决完之后,那就意味着一个大的问题解决了,大多数市面上比如说有一些类似的产品就做到那个程度,但针对业务场景需求就需要有一个非常强的,能不能有一种丝滑的感觉,我们需要做到一个非常重要的能力就是鼠标的同步,鼠标同步大家可以想一下这种场景下一个巨大的挑战,什么时间发送一个鼠标状态到对端,非常多人的时候可以想到中间会遇到一个巨大的渲染的压力,刚开始实现的那个方案感觉卡卡的,大家可以感觉到移动沟通上面鼠标状态会有一些延迟。
实现这个技术手段的时候应用到架构选型的优势,跟我们再追加一些核心的特性,第一我们用的是,一个是先用 SVG 的鼠标绘制,在原来可视化上追加一个新的隐藏图层最高层的层级,这样鼠标的核心点就可以实现出来。
现在整个浏览器动画技术里面最核心的函数接口就是这个接口,可以实现动画效果,这里面会深度使用这些点,大家可以看一下鼠标同步流程,核心是这样的流程。
鼠标同步流程图
第一、我们绘制出来对端鼠标的效果,加上光标,加上信息。
第二、我们监听本地的鼠标事件,移动之后循环把这些事件插入到具体队列里面,然后再发往服务端。
svg 的绘制相对是比较容易的,大家可以看一下这几个核心点,整体上主要代码采用的是 svg 的整个方案,最好就是一个结构化文档可以便捷的进行传输,这是这个图层的效果。
再看这个动画的实现,体现了两个技巧,第一是什么时间发送一次,快的话压力很大,慢的话延迟很高,我们调的节点是500毫秒,搞前端的都知道截流可能触发很多次,每500毫秒做一次数据。我们的绘制间隔是400毫秒,这个是精心调整过,在对端双方正好非常丝滑的感觉,你能感觉到稍微有一点点的跟随,这是最好的状态,所以这就是我们当时最核心的数据。
这个是核心的鼠标同步算法,这里面用两个核心接口,通过 CS3 整个的效果可以把一个位置不断地滚动,非常流畅,这种模式下基本上看起来就跟真的光标一模一样。所以这就是,原来我们觉得会有挑战的点,但其实可以很好的化繁为简。
— 4 —
组建同步
这个方案解决完之后还有一些关键挑战,比如,我们接下来要讨论的组件动画的同步,大家可以重新回想一下刚才的视频里面播的是,整个组件移动的过程也要同步过去,现在国际上做这种技术方案,大家的感受都是滑过去之后对方直接就蹦过去了。
这个动画的拖拽效果也有非常详细的流程,我们的模式是增加一个选择的监听,本地把这些监听发送到云端,对端开始接受,接受之后创建一个专门的队列,每一端的操作都有一个对应的队列,这样整个体系里面会把每个端的高量全部渲染出来。之后再进行计算处理。
组件同步流程图
这个处理需要有非常多的技巧,又回到刚才说的技术选型的重要性,所以我们的处理办法是看起来很吓人,实际上是非常好的,中间会经历很多次的阐述、添加,但这就是我们核心的流程。
大家可以看一下关键数据的情况,非常关键细致的点决定了交互体验。组件轨迹同步,这是相关的核心代码,有兴趣的话可以找我进一步沟通。
— 5 —
视角同步
还有一个关键挑战,这个挑战来自于视角同步,大家都知道整个架构绘图方面可能是很大的绘制白板,可能脱离出视角,这个情况,超出这个视角之后就不知道对方在更新什么。
而我们的处理办法是,需要计算每一次新进来的行为有没有在对方的视角内,如果有的话我们有两种处理方法,第一类是点击追随,追随完之后,别人移动什么视角对方可以直接追随,我们不需要任何的动作。第二类是其他追随,告诉他对方已经出了整个绘图区需要追随,再去点击,这也是我们的核心处理。
这里面最重要的是视角同步整个技术处理,第一一样的会追随鼠标状态,然后关注每个图形的位置,换算对方过来之后有没有超出区域。最重要的是拿到对方视角的位置,然后再分析有没有大于我们的区域。
视角同步算法,通过本地的 ScrollLeft 去判定,之后一样通过动画的处理函数去进行整体的处理。
视角同步流程图
大家跟着我一起感受了整个从技术选型到框架架构方案,再到每一个绘制技术,到最后整个方案选型的整个过程,目前,我们的核心策略是打造一个真正云端化在线协同无缝沟通的环境,尤其是在咱们技术深度的沟通协作环节。
END