之前做了个玩具叫做 Cumulo, 大致意思后端计算数据, 通过 Diff/Patch 发到前端,
那么前端浏览器的 Store 就不需要业务逻辑了, 从而减少开发.
然而这种做法存在天然的缺陷, 首先, 性能问题, 其次, 持久化问题.
其实都可以归结为性能, 要性能, 就必须做增量, 那么整个架构就崩溃了.
这篇文章尝试描述一下稍微正常一点的, 基于数据流来设计架构的一个构想.
由于后端开发经验的欠缺, 我并不打算给出可行的方案.
在开始之前, 先回顾一下实时 Web 应用的架构设计.
首先在前端 Model-View 分离是第一步, 以便解放 View 的开发效率.
这时的数据流, Model 的数据发送到 View, 而 View 的更新操作回到 Model.
(这里的 Model 接近 Store, 并不是单纯数据, 而是包含更新逻辑):
接着, 把 Server 重新放回来, 大致就到了 Cumulo 的情况,
这时的数据流, 数据直接发送到服务端, 前端 Model 同步服务端,
最后再回到 View, 这时 Model 就成为一个中间过程了:
那么结合上边两张图, 把这部分简化, 基本就回到第一张图的情形,
区别是, 这时 Model 换成了服务器, 而数据流从服务器流行浏览器:
当我们考虑数据库, 特别是数据库比如是增量处理, 问题就来了,
首先, 数据发送到 Server 而不是 Database, 因为 Server 才有逻辑,
其次, 不能把 Database 整个数据流发给 Server, 因为太大了.
Cumulo 中用的是 Diff/Patch 方案, 而这对于 Database 来说并不可行,
所以实际情况就挺纠结了, Server 回到了 Controller 的角色:
最后为了性能, 更新逻辑还需要从 Database 拿开, 而让 Model 回来,
那么 Model 一方面要处理数据请求, 一方面要处理推送, 只能增加,
整个数据流也多了一些线路, 变得复杂起来, 这也是当初简聊大致的架构:
不过这个图并不严谨, 比如 Database 和 Server 的具体关系很难画清楚,
而且请求当然是访问到一个 web server 而不可能直接放到数据库的,
这个图的重点是, 相比原来的一个流, 现在存在两个流, 架构已经变了.
而数据通过两种途径来获取:
数据抓取, 访问页面时直接抓取的数据, 以及抓取历史
推送, 用户使用过程中, 从其他客户端获取的更新
问题是, 如果不能进行简化, 从而减少业务代码的编写, 思考就没有意义了,
这两个数据流的计算方法并不一致, 无法合并成一个,
所以我考虑, 从另外的角度去思考怎样构造出一套框架来处理数据流,
所以我整理了一下聊天室需要的常见操作:
切换聊天室
抓取首屏消息
抓取消息
接收消息更新
查询历史消息
用户登录
用户权限验证
对于前面四个操作我比较在意, 因为之间存在着一个共性,
比如一个消息流, 就会有, 切换, 抓取, 历史, 更新, 这些个操作,
而整体看来, 其他的能够抽象到流的数据也可以复用这个套路,
那么整个应用的页面切换, 数据查阅, 数据更新, 能放进一个统一的框子,
也就是, 路由切换时选择客户端订阅哪些流, 然后按流进行浏览.
当然其中还是存在一些问题, 需要继续思考,
消息列表是流, 那么用户配置是流吗?
配置经常是 JSON 对象, 要变成流, 就要把不同时间的修改操作也涵盖进来,
但是这还是会涉及到新的问题, 每一条消息都可能修改, 那么也是流,
结果我们需要面对一个复杂很多的流的概念.
另一个是数据的关联, 消息当中会有附件, 聊天室会有成员,
数据的关联如何处理? API 的设计怎样对应的界面, 而两者又进行解耦?
如果数据之间还出现循环的关联关系, 整个方案是否将要失效?
这是一个相当麻烦的事情, 最开始可能还是要尽量避免掉.
此外, 即便解决了上边两个问题, 前面列表当中剩下的选项依然要处理,
权限系统, 搜索系统, 两个是独立于流的结构之外的, 无法同时抽象.
更加远的问题, 数据库和服务器可能是分布式的, 还会有更复杂的数据流.
所以实际上抛出来更多问题了.