在企业办公场景中,“打工人”们的工作协作基本离不开 IM 软件,而大家却也常常被图片消息确认难这样一种困境所困扰,比如:当群组里有一个人发了一张技术架构图请其他几位同事做确认时,接收信息的每一个人可能都需要在图片上进行标注,用画笔圈出需要修改的地方,然后保存到手机再发送到群里,还可能要反复修改,整个过程十分不顺畅。在这种需要多人协作的场景中,工作效率就大大降低了。

但现在,情况开始有了转变。

1 月 14 日,钉钉正式发布 6.0 版本,其战略定位也从过去基于 IM 的协同办公平台,升级为企业级协同办公平台和企业级应用开发平台,这是继“云钉一体”战略后,钉钉最重要的版本升级。

而此次钉钉众多上新的能力中,包含了一个叫做“一起标注”的功能,它可以实现像编辑文档一样多人、实时编辑一张图片。只要点击图片进行标注,所有接收到图片信息的协作者就可以看到编辑过程及编辑者的名字标签,很好地解决了我们开篇提到的如何在图片消息的讨论上实现更高效的问题。

可以再设想这样一个场景:团队欢迎新同学加入一起聚餐,合照发到群组中,大家可以一起在照片上涂鸦圈人,新同学将自己圈出来,照片上会自动显示名字标签。“大家看看新来的 UED 同学在哪里?”,通过这种多人实时互动,给工作带来更多的趣味与温度。

“一起标注”功能展示

在“一起标注”功能的背后,钉钉的自研技术:协同框架技术也浮出水面,其目标是希望能够降低多人实时协作应用开发的门槛,通过协同组件、协同数据结构等服务让开发者更专注于其自身业务。“一起标注”只是基于协同框架的其中一个 Showcase,在这套协同框架下,还有更多的协同应用等待大家去开发。

为什么要做这样一套协同框架?多人协同应用开发难在哪?

如 Google Docs、Trello、石墨文档、腾讯文档……各种各样的协同办公工具为什么会受到企业的欢迎?就是因为它们在一定场景中能够解决团队协作的需求,“多人”、“实时”、“协同”是团队协作的关键点。

对于普通开发者来说,开发一个本地的单机版应用很容易,但要从 0 到 1 开发一套支持多人实时协作的应用则要面临底层工程架构、算法相关的复杂问题,技术门槛较高。

在底层工程架构方面,需要关心平台适配、网络、存储等问题,开发者可能需要做 Android、iOS、Windows、Mac、Web 版本、小程序端等多平台的适配;而且还需要关注网络问题的处理,如丢包、无网 / 弱网问题、离线状态恢复问题、网络容灾等等,最终保证信息的实时推送;另外,在数据存储上也需要考虑保证在无网 / 弱网环境下应用的连续性。而在算法方面,如何解冲突?即不同的操作之间的合并、冲突解决等等也是开发者将要面临的问题,因此要设计出满足多人协同的数据结构需要庞大的技术投入。

钉钉面向 To B 的企业级市场,离不开创新产品与技术。因此,钉钉的工程师们开始思考一种方式,如何能够用一套框架解决这个大难题,让开发变得更容易。

钉钉依据技术积累攻克难关

协同框架技术服务架构

在摸索创新的过程中,钉钉工程师们想到:无论多人游戏、多人在线文档编辑还是 IM 聊天等产品,其实都是协同应用,那么是不是有一套通用的协同框架可以被抽象出来?而且能够让上层业务开发者基于这套框架,快速地开发出他自己的协议应用。这是很关键的思考,在这种想法的指引下,最后把协同框架分成三层:协同组件层、协同小程序与数据结构层、协同引擎层。

最上面一层是组件层,叫协同卡片,是可视化的,开发者可以直接拿来用,比如像“一起标注”的画布功能就是一个协同画布组件,本身就具备多端、多人实时协同能力,也已经带有前端的渲染工作。开发者可以用协同组件搭积木式地组装出自己的协同应用。

中间一层是协同小程序与协同数据结构,这是不包含 UI 的数据框架层。提供的小程序 SDK 包含了一系列基础数据结构,类似于 C++ 的 STL、JAVA 的 JDK,SDK 也提供了例如 CoString、CoBoolean、CoMap、CoList 与 CoPixel 这样的基础类型,开发者通过这些数据结构达到多人协同和多端协同的目标。比如开发者想做一个多人协作的 “To Do List”的功能,那么通过使用协同框架,进行简单编程操作即可,并不用关心网络通讯以及复杂的操作合并冲突解决的问题。

最底层是引擎层,如果以上没有开发者想要的能力,也可以根据协同框架开发一个新的数据结构,那么在这层则需要进行很多接口的实现,包括初始化、快照、冲突解决等。相当于依据协同框架开发一个第二层的数据结构,再进行使用。

中间层的小程序框架与数据结构的抽象工作,解决了开发易用性的问题,顶层甚至不用编程直接用组件就可以搭建。协同框架通过上两层的技术服务就可以实现大部分的数字化应用创建,而最底层可能交给高级工程师们去实现。协同框架面向不同的开发者,才能让生态良性发展。

协同框架开放背后,有哪些亮点技术支撑?

攻克这一套协同框架,钉钉采用了很多业界内突破性技术。

数据通道上,协同框架底层的推送通道使用了钉钉的数据同步平台。数据同步平台作为钉钉的基础设施,为钉钉数百个业务提供可靠的服务端到客户端的数据下发通道,提供了统一的海量、可靠、实时、全端覆盖的数据同步服务。数据同步平台同时支持推送实时信令、即时消息、可延时数据等不同时效等级,通过通道隔离、下行数据优先级智能调度、弱网感知优化等多种手段,保障了各个接入业务都能使用到高性能、高可用的数据同步服务。在 2020 年疫情期间,数据同步平台很好地支撑了钉钉的视频会议、IM、DING 等多个重量级产品,每日同步数据数千亿,系统流量高峰时刻 TPS 超过千万。

底层设计上,引擎将协同过程抽象为有限状态机模型,它包括离线工作和跨多设备多用户协同的能力,同时能提高数据的安全性、隐私性、长期保存性和用户控制权,保证在网络状况不佳的环境下,也能够实现无差别协作的工作。比如在弱网、离线情况下,也能保证能够继续进行图片标注,在网络恢复后操作同步。协同框架提供了多平台的 SDK,包括主流移动端、桌面端、Web 端,也包括服务端 SDK。架构设计上基于对等原则,所有接入 SDK 的协同端,不管是客户端、Web 端还是服务端,都是对等 Agent。

同时,多人实时协同问题的本质某种程度上是一个分布式领域的问题,钉钉协同框架结合了操作变换 OT(Operational Transformation)与无冲突复制数据类型 CRDT (Conflict-free Replicated Data Types) 技术,用于实现协同操作合并与冲突解决,并让各个协同端状态达到最终一致。对于不同的协同场景,可以选择其合适的协同算法与协作策略,但这些底层复杂的技术细节,对于使用协同框架的上层业务都是透明的,开发者只需要操作协同数据结构与协同组件即可。

以本次钉钉 6.0 发布的“一起标注”功能为例,这个产品功能的实现是基于名为 CoPixel 的数据结构。CoPixel 本身作为数据层,与 UI 无关,用于承载笔画图形的数据,而 UI 层则通过将 CoPixel 封装为一个协同画布组件。用户在协同画布上每画一笔,都会对 CoPixel 产生对应修改,进而自动协同到所有参与协作的用户端,其他用户端的 CoPixel 会回调 UI 层的画布组件,从而新笔画得到展现。当多名用户同时操作,这些动作会合并并自动解决其中可能产生的冲突。

未来,拓宽边界与开源

协同框架是支持多人、多端、多场景、多应用的,在未来的发展规划中,会不断拓宽边界,发挥协同的最大价值。可以进行跨应用协同工作的打通,实现跨应用、跨设备、跨网络线,实现不同应用的数据共享,比如也许在 CRM 里做某些操作时,ERP 系统也能进行协同,让数据同步。在未来移动开发市场上,也期待协同框架带来的新变革。

协同框架借助了钉钉 IM、文档、小程序、终端研发等团队在以上方面的大量关键技术积累,但也还有很多功能上的问题需要钉钉工程师们持续打磨,对于内部团队来说,还需要修炼内功。未来,协同框架必定会走上开源之路,这也是钉钉在计划内的事情,通过开源,让更多优秀的开发者加入钉钉的生态中来。