短视频|成本节省 50%,10 人团队使用函数计算开发 wolai 在线文档应用( 二 )


自 2020 年 6 月 15 号业务上线以来 , 我们从来没有遇到服务 down 掉或者是需要下线维护的问题 , 而这些问题是使用函数计算前的常见问题 。 以往一旦遇到这样的问题 , 我们需要耗费很长时间寻找发生问题的原因 , 可能需要升级 Web 服务 , 加几台机器 , 甚至做反向代理和负载均衡……即使这些工作全部做完 , 再上线的服务还是会有维护时段 , 我们依然很难做到服务持续在线上 。 因此函数计算对我来说很重要的一个功能点就是持续服务的能力 , 通过使用函数计算 , 我的业务可以稳定地、持续地增量发布 。
我在上一家任职时 , 每两周做一次版本发布 , 每次发布都有非常详细的发布列表 , 发布涉及的条件、依赖项非常多 , 需要运维去跑的脚本非常复杂 , 可以说只要出现一丁点错误 , 整个发布可能就会演变成一个小事故 , 甚至是大事故 。 当我们把整个架构放在 Serverless 上 , 把所有的功能进行拆分之后 , 发生事故的概率大大降低 。 即便发生问题 , 我可以通过快速回滚来解决问题 。 现在我们的研发习惯每天至少发布一个版本 , 当天所有解决的问题都会发布 , 相比传统的软件公司来说 , 部署在 Serverless 架构上我们的迭代速度会快很多 。
快照保存系统 , 解决协同编辑算法问题 对于 wolai 这样的协同办公产品 , 协同编辑是产品的重中之重 , 这个功能对于算法的要求很高 , 通过使用函数计算我们同样很好的解决了这个问题 。
wolai 云端笔记功能有一个信息块(Block)的概念 , 就是将用户所能接触到的最小信息单位从‘文件’缩小到‘信息块’” 。 “信息块”可容纳文字段落、表格、清单 , 以及嵌入来自外部的图片、视频等信息 , 且可被简易编辑、移动 , 经实时呈现后组成页面 。 所以接下来我会以“块”来指代信息块 。
红底之上都是一个个独立的块
用户每次按键操作后 , 我们的前端都会有类似快照的保存机制 。 如果用户按键非常快 , 那他的多次按键操作可能在某一个时间切片中组成一个 transaction, 发回这个函数计算 。 然后我们就会记录下这些操作 。 当第二个用户同时进行按键操作时 , 如果他也针对同一个块做按键操作的话 , 他也会触发同样的操作 。
我们会在函数里面去计算这些操作用户对这个块实际影响先后的顺序 , 最后得出它应该变成了一个什么样子 , 然后函数计算还会发出一个队列的请求 , 当有任何一个块 , 或者说它所属的页面发生过这个变化的事件之后 , 它会丢到这个 redis 里面 , 5 分钟之内一旦有一个块或者一个页面有过更新之后 , 我们会再调一个函数 , 把整个页面和整个块去生成一个一个快照 。 所以我们把函数和队列调用结合在一起做成了一个自动化的系统 。
用户一旦在页面或者块上有编辑 , 我们都会在固定时间段生成一个快照 。 我们现在针对单个块(相当于单段文字或者说一个图片这样的一个最小单元)一分钟保存一张快照 。 相当于在1分钟之内 , 用户只要有过更新 , 我们都会把它整体变成一个快照 , 然后放到 OSS 上面去 。 如果每一个块是频繁更新 , 那么 OSS 上针对这个块会有特别多的一分钟的快照 , 目前我们 OSS 上差不多都已经有 10 亿多个文件了 。 如果是页面级别的编辑 , wolai 5 分钟去保存快照 , 频率会低一点 , 通过函数计算和队列结合 , 我们制作了一个快照保存系统 。
wolai 的 Serverless 架构图
使用 Serverless 解决的问题 通过研究 wolai 的用户行为会发现 , 我们的用户一般会在每天早上上班时打开 wolai 文档 , 然后他/她会在一天之中持续使用直至下班关闭 。 我们的用户并不会像小程序用户那样 , 需要快速打开应用 , 然后即用即走 。 相反 , 他们对于应用的初始加载速度没有特别高的要求 , 因此我们关注的重点并不是服务器端的渲染问题 。 通过研究用户习惯 , 我们更关注用户在打开应用后 , 操作的每一步是否能够快速响应的问题 , 这里面涉及到两个点: