在 Vanke 近一年的工作,我们重写了原本的 2.0 系统。现在也基本进入稳定状态。 接下来的工作,更多地是用运营数据说话,尽可能通过技术手段影响我们所在的行业。

R2D2 就是这么一个背景下诞生出来的项目。本质就是一个数据可视化的项目。

讲讲两个 App

我们对外产品主要是 “住这儿” 和 “助这儿”,用户分别是业主和员工。关于产品的设计不是这篇 Blog 要讨论的,所以不评论功能是否合理等等。

“住这儿” 面向业主。提供了缴物业费、查询邮包、提交报事、反馈、物业评分等物业支撑功能,同时也提供了一些社区活动、帖子,以及我们发送通知的渠道。

可以收集的数据有:

  • App 的普及率;
  • 不同社区业主的活跃程度;
  • 不同社区业主使用 App 的主要目的;
  • 不同社区物业评分情况;
  • 业主更喜欢什么功能。

“助这儿” 面向员工。提供员工工作所需的功能,签到、抢单、查询业主信息等。

  • 员工在岗情况(在岗人数、位置、岗位类型等)
  • 任务完成情况(完成时间、评分)
  • 报事来源(来自业主、员工等)

R2D2 将从两个 App 收集到的数据汇总,并且以各种图表展示出来。

R2D2 架构

就当前而言,R2D2 需要显示的数据有:

  • 员工在岗情况;
  • 几种类型岗位的在岗情况;
  • 每日新增任务(报事)数量;
  • 每日任务完成情况;
  • 服务评分情况;
  • 报事来源;
  • 普及率情况;
  • App 日活;
  • 岗位在岗大致地理位置。

以上的数据大概分为三类:

  1. 通过 RDS 分析得出,例如普及率、服务评分等;
  2. 通过较长时间的日志分析得出,例如日活;
  3. 实时分析日志获得,例如在岗人数、在岗地理位置。

上面的数据中,第 1 类和第 2 类数据,后端都可以通过普通 API 提供给前端给予展示,而第 3 种则需要做到实时提供。

实时的请求,以前有 文章 讨论过,大致分为:

  • 轮询,伪实时
  • 长轮询,伪实时
  • WebSocket,实时

三种方式,我比较希望使用第一种轮询,因为实现最简单,只需要 Ajax 定时循环请求就可以,当然对服务器压力会大。(但毕竟这个是给内部人看的,轮询也够了) 长轮询需要 Tornado 的异步请求支持,个人不太想用 Tornado,也放弃了这个方式。 但在 R2D2 中有这样的一个需求,当员工签到,需要在一个地图上显示员工签到的动画。 如果用轮询,n 秒请求 1 次,如果 n 太大,那么 n 秒内登录 k 个员工,这 k 个员工的动画就会在一瞬间同时播放,效果会变得很奇怪。 但如果 n 太小,又会对服务器造成很大的压力,所以对这部分数据,选择用 WebSocket 来推送给前端。

所以整个 R2D2 大致的架构如下图:

架构图

R2D2 前端

R2D2 前端采用 Vue 做基本框架,D3 来协助绘图。

上一次认真写前端是一年前还在一熊的时候。过去一年,前端新出了几个框架。 对比 Angular、Vue 和 React 最后决定用 Vue。 相比之下 Vue 和 Angular 比较相似,而且比 Angular 要轻量级,上手快。

Vue 相关的介绍,在 另一篇文章 里有讨论。 D3 相关讨论在 这里

R2D2 后端

R2D2 后端氛围两部分,普通的 API 以及 WebSocket。

APIs

例如日活等数据,是非实时性的,这部分数据通过 SQL 就可以计算得到,因为一段时间内数据是不会变动的,可以存放在 Redis 中,减少对 RDS 的压力。

除了日活以为,例如当前在岗员工情况也是通过这种方式提供数据给前端,前端通过轮询取数据。

WebSocket

目前 R2D2 对 WebSocket 的应用还比较轻,主要是用来分析日志并且将用户请求信息发送给前端进行渲染。大致的流程是这样:

多个服务节点将日志实时汇总到日志服务器上,日志分析程序分析汇总到的日志,解析出当前用户的行为,再转换成对应的数据协议传送给前端,前端接受数据,在地图上标记位置并渲染对应的动画。

R2D2 效果

目前 R2D2 的大致效果如下:

效果图

R2D2 有什么问题?

R2D2 目前还存在不少问题:

  • 前端性能,图表太多,加上地图部分每个员工都对应一个 HTML Node,运行久了之后会动画就会特别卡。在 Chrome 这种吃内存的浏览器下,体验更明显,甚至直接拖慢操作系统。
  • APIs 的性能。上文说到,APIs 数据是通过 SQL 进行计算。有部分数据 SQL 执行时间需要几秒,虽然加上了缓存,但首次加载的体验是非常糟糕的,解决办法可以异步计算。
  • 上文说到,前端通过轮询方式获取部分非实时数据,就目前而言还能撑得住,(毕竟用的人还不多啊!QwQ),但用的人多了之后,还是会对服务器、数据库造成压力。解决办法还是常规套路,Redis 缓存一段时间,牺牲首次访问的用户体验;异步计算复杂数据;最后还可以上 WebSocket。
  • 稳定性问题。目前后端 API 还处在开发阶段,运行在单进程 Debug 模式下,基本上每天会挂一次,初步怀疑日志切割的时候导致日志分析程序 FD 异常了,需要好好研究一下这块。