著作权归作者所有。商业转载请联系 Scott 获得授权,非商业转载请注明出处[务必保留全文,勿做删减]。
数据只有被看见,真相才浮出水面,数据跳动在大盘,洞察才形成预判。
今天 2020/1/7,到小菜整整 2 年半,看到团队在数据报表量产和可视化上面有了新的成果,这些年来也了解到前端后端面对不计其数的数据报表和后台可视化大盘,真心苦不堪言,就趁这个节点,跟大家聊聊两年半来我们是如何从前端来驱动数据报表量产和可视化大盘的技术探索。
首先上结论:
- 公司的数据仓库(简称数仓)要投人力持续建设,它是报表及可视化的基础
- 前端自研报表及可视化会有较高的成本,需要谨慎再谨慎,竞品调研再调研
- 魔改 Metabase 是一个不错的选择,需要前端学习 Clojure 和熟悉 React
简而言之,先推动技术团队把数据仓库建设到基本成熟,再来基于 Metabase 魔改出自己的报表和可视化业务后台,这是一个可取的套路,得出这个结论,是因为两年半的探索我们有斩获也有疼痛的教训。
当然一路自研过来,我们也调研了很多方案,无论是商业付费还是开源,对第三方可替代竞品的选择标准如下:
- 代码开源免费,有团队/人持续在维护
- 产品交互流程易用可定制,有设计感
- 技术栈对前端友好,学习上手成本低
阅读两篇旧文,有助于大家理解下文:
为什么数据报表是刚需
不管是 toB 还是 toC 的公司,无论是 +互联网还是互联网+,都对数据报表有着近乎疯狂的依赖,这不仅仅是像马老师说的我们正在进入 DT 时代,数据运营甚至数据智能价值挖掘和应用越来越普及,而是对于任何一家高速迭代的互联网公司,在产业互联网的大背景下,在中早期各种红利逐渐消逝的前提下,基于数据的成本意识和精细化运营能力越来越考验一家公司在所谓寒冬活下去的实力。
业务现场无时无刻都在产生着数据,通过什么途径观测业财健康直接决定一个公司/一条业务线的顶层决策,顶层决策有何等重要,促成决策的数据报表就有多重要,所以一个公司只要上了信息化系统,数据报表都会成为绝对刚需。
基于这个刚需,有的公司招专门的 BI 工程师,组建算法团队甚至大数据团队,有的则是业务方直接把要看的字段丢给开发团队,让前后端工程师,一个写跨库跨表的 SQL API,一个写能筛选日期和排序的 DataTable 页面。
显然小菜早期,就是以 SQL -> API -> DataTable 的流程开发报表,效率极低,成就感极弱,前后端成长极慢,带来的影响有很多,比如工程师更不稳定,比如业务决策等待的周期更长,比如报表的零散维护出错率更高...
第一波探索 - SQLEditor
启动数据报表是在 2017 年 7 月份,届时市面上还没有较为成熟的开源方案可选,包括目前的 Metabase,调研无果后,我们选择了纯自研,目标是让产品经理/后端开发可以快速在线制作报表并渲染出来。
**
方式是参考数据仓库业务表的文档,在系统上快速的定义报表列的中文名称以及对应的库表字段的查询(比如产品经理可以不借助开发资源,自行查询销售的周市调次数和周个人交易单量这样的简单报表),由于是取代运营本地人肉的 “搭表格”,因此这个系统取名叫做 “大表哥”,它的技术栈的进化如下:
早期技术栈
- 前端:React + Ant
- 后端:Node.js/Koa2/MongoDB/RDS
- 服务器:1 台 2 核 4G Centos
功能清单:
- 报表需求提交(看某业务的哪些数据)
- 报表加工(在后台网页编辑 SQL)
- 过滤组件(基于某字段做数据筛选过来)
- 报表查看(按照一套模板渲染报表)
- 报表导出(Excel 格式导出)
技术栈缺点:
- Koa2 是一个精巧精简的 Node.js 框架,不是一个企业级的框架,从 0 开始配置开发,成本还是比较高
产品交互易用性:
- 前端页面的交互未经过设计,前端自行设计,比较粗糙难用
中期技术栈
- 前端:React + Ant + Apollo + React Native
- 后端:Node.js/Egg/Python
- 服务器:1 台 2 核 4G Centos
功能清单:
- 报表需求提交/加工/查看/导出优化,及更多过滤组件
- 报表权限(谁能看哪些报表)
- 数据权限(谁能看哪些报表背后数据库的哪些表)
- 透出报表到 App 端(ReactNative 报表组件)
技术栈缺点:
- 低版本 RN 报表组件开发踩了不少坑
- Python 加工数据性能压力比较大,且比较吃 CPU,无法高效的解析二进制类型的数据
产品交互易用性:整体的产品设计较粗糙,菜单管理权限管理粗暴,维护成本较高,导出功能不稳定
目前技术栈
- 现在:AntD + AntV + Apollo + Rxjs + React + Rematch + React Native
- 后端:Node.js/Egg/Envoy/Python/gRPC/Docker
- 服务器:1 台 4 核 8G Centos + 1 台 2 核 4G Centos
功能清单:
- 报表需求提交/加工/查看/导出优化(分布式 Docker 部署)
- 报表权限/数据权限接入权限中心
- 报表到 App 端的组件化丰富与开发
技术栈缺点:
- 大量的报表查询与导出,给 RDS 带来较大查询压力,同时超大报表的导出,服务器 I/O 压力大
产品交互易用性:
- 整体功能可用,但流程偏复杂,设计感不强
报表制作后台,可以跨库跨表的查询数仓的数据,自由度很高:
报表展示页面,自动关联各种筛选组件,增强报表的检索功能:
第二波探索 - 可视化大盘
启动可视化大盘是在 2019 年 1 月份,届时销售征战四海,业务遍布全国各地,需要有一些更宏观、更易于理解、更易于诊断和决策的视角来看时间线上的业务财务变化,以及跟进地面部队的 KPI 完成情况,就启动了数据大盘这个项目,因为它需要有很强的定制性(比如更改 KPI 和录入新指标等),而且比较紧急,除了付费用阿里云 DataV 做一些过渡外,就在大表哥的基础上启动了数据大盘的开发,让它可以直接长在数据报表之上,技术栈情况如下:
当前技术栈
- 前端:React + Apollo + AntV
- 后端:Node.js/Egg/Python/C#
- 服务器:1 台 2 核 4G Centos
功能清单:
- 元数据过滤聚合
- 10 个图形组件可选择
- 自由挑选组件组成看板
- 自定义看板布局
- Redis 缓存数据
- 看板查看权限
- 图表动态筛选组件
技术栈缺点:
- 明细数据数据量大,导致前端加载慢
- GraphQL 无法 URL 缓存
- C# 计算 Excel 方案吃 CPU,服务器压力太大
- Python 计算性能差
产品交互易用性:编排流程复盘,需要定时触发任务加工数据,编辑体验和调试体验不好,可视化的大盘性能不好
除了传统的饼图柱状图二维表等等,也有偏定制的跟踪 KPI 的录入式卡片集:
第三波探索 - Metabase
启动 Metabase 是在 2019 年 7 月份,届时 Metabase 趋于稳定,公司的数据仓库建设也更加成熟稳定,可以面向 BI 团队接收需求来开发一张张业务宽表,具备了可快速查询的条件。
另外需求也有变化,更多端的报表及可视化的透出需求越来越多,比如透出到钉钉 H5 上,内部的 App webview 内,PC 中后台的系统中,甚至是客户的微信 H5 账户主页上,就启动了这一次的探索:基于 Metabase 来魔改报表及图表的拼装流程,公司自己登陆系统/权限系统的集成,与原来的大表哥做融合升级抽离微服务等等,基于这么多可视化大盘的需求,我们把这个经过魔改的 Metabase 改名叫 “大盘子”,它的技术栈情况如下:
当前技术栈
- 前端:React + Redux + D3
- 后端:Clojure/Docker/RDS
- 服务器:1 台 2 核 4G Centos
功能清单:
- 创建需求
- 创建仪表盘(看板)
- 创建定时任务(发送需求至邮箱)
- 自动分析数据库数据
- 14 个可视化组件
- 自动分析生产仪表盘
- 下钻分析
- 支持多种数据源
- 权限管理
技术栈缺点:
- 前后端耦合
- React 太低,只有 15,无法使用很多社区资源
产品交互易用性:
- 汉化的效果不佳,整体的设计稿偏朴素,流程上手有一定的理解成本
预期技术栈
- 前端:React + Redux + d3 + AntV + AntD + Storybook + gRPC
- 后端:Clojure/Node.js/Envoy/gRPC/Python/Docker/RDS/Druid
- 服务器:3 台 2 核 4G Centos
功能清单:
- 创建需求
- 创建仪表盘(看板)
- 创建定时任务(发送需求至邮箱/钉钉)
- 自动分析数据库数据
- 22+ 个可视化组件
- 自动分析生产仪表盘
- 下钻分析
- 支持多种数据源
- 数据权限管理
- 钉钉小程序组件
- 多种主题(目标替代已付费的 DataV)
- 模块组件
- 分布式服务
大表哥和大盘子生产链路
大表哥一句话
网页版的报表编辑器和展示工具,具备量产数据报表和可视化搭建图表的能力。
大盘子一句话
基于 Metabase 魔改的系统,具备数据报表和图表搭建的全链路生产与应用能力。
生产报表链路
大表哥,更偏工具属性,它的生产链路是从一份报表的需求提交开始,比如想要一个报表,看所有门店昨日成交 总单数、GMV...假如门店业务的 10 个表头业务字段也定义好了,接下来 PD/开发 进场:
一、 制作阶段:
- 从报表需求进入到网页后台的 SQL Panel 制作页面,引入各方数据表(跨库跨表)
- 对各种表进行 join,提炼业务字段并定义、过滤(数据内容、数据权限管理)、数据聚合、排序和分页规则
- 最终生成两套 SQL,一套是能查出这份报表的 SQL 本身,一个是对它的 count 操作
- 生成的 SQL 以元字段和特定规则持久化到 MongoDB,报表制作完毕
二、 渲染阶段:
- 从 MongoDB 中拿到特定报表的 SQL 规则
- 把规则转成 SQL,连接 RDS(MySQL) 进行 Query
- 查询后拿到的 Rows Data 返回,经由 GraphQL Query Endpoint 进一步筛选聚合
- 网页拿到二维数据及表头数据,开始渲染 Table 渲染及配套的过滤组件
三、导出阶段:
- 导出 Excel 依靠另外一台服务器,做 Excel 的流式存储
四、透出阶段:
- 透出到移动端,借助于额外开发的 RN 移动报表组件,来实现九宫格、卡片、列表、Tab、复合筛选等报表功能
五、图表制作:
- 在 1 基础上,定时更新,过滤、聚合(统计逻辑)、将大盘背后的数据,定时持久化到 Redis(单个宽表)
- 挑选 redis 报表数据源,二次加工数据,编排组合这些二维表和图表,生成特定业务域的可视化数据大盘
六、定制通知:
- 在 5 的基础上,可以以关注的形式跟进大盘的数据变化,获得实时的钉钉消息推送
从制作到展示,到透出到移动端,整个报表链路是闭环的,但是也有不足和缺陷:
- 移动端只能适配 APP,无法适配 H5,并且强依赖 APP 的热更新发布
- 移动端只建设了二维表组件,未建设可视化组件(这也不是 RN 强项)
- 产品的 SQL 能力有限,跨库跨表查询容易把数据库查挂,或者拖慢整体的性能
- 数据仓库的底层未建设,放开跨库跨表查询的权限有安全风险
- 编排可视化大盘与报表的绑定太过耦合,对其他数据源的兼容度不好
- 报表、可视化以及移动端的 RN 报表组件内,对于权限的管理不够体系化
大盘子,虽然也是工具属性,但由于它是站在了数仓宽表基础设施完善的基础上,所以针对单表(可额外 Join 一张表)的数据聚合、组合和图表编排能力更完整,它的主流程如下:
一、数据源创建阶段:
- SQL Panel(单库单表,额外 Join 一张表),引入宽表数据源
- 字段定义、过滤、聚合、排序生成 SQL(可以预览 SQL)
- SQL 规则持久化,数据源定义完成
二、图表/二维表制作阶段:
- 在 1 的基础上,透出二维表/图表类型的映射选择
- 针对表的字段再定义
- 渲染展示和导出 Excel(导出性能不好)
- 不断的重复 1 到 2 的图表/二维表选择,制作很多单图表组件
- 组合编排这些单图表组件,生成可视化数据大盘
三、透出阶段:
- Webview url 内嵌或者组件引入,渲染特定的二维表/图表/综合大盘的 PC/H5 页面
显然大盘子的链路更短,而且可以被 webview 嵌入,可以充分利用浏览器能力,它的发布效率更高,特别是 Bug 修复和大盘具备迭代的时候,但大盘子的报表导出性能不高,同时对于偏录入式的可视化组件支持不够,以及 webview 自身的加载性能问题。
自研与半自研的价值比较
大家如果对比上面三波探索的功能点,会发现这个公式:
大表哥(自研) + 大表哥可视化(自研) ≈ 大盘子(半自研)
也就是我们辛辛苦苦迭代了 2 年的的数据报表和可视化的成果,也就能顶上开发半年的 Metabase 的成果,WTF...
如果让我们重新回到 2017 年,我们一定会做如下的选择,来避开两段弯路:
- 在数据仓库不 Ready 的前提下,我们不会启动数据报表平台的建设
- 在 Metabase 趋于成熟的时候,我们会选择用半自研替代全自研
提到价值,就一定是这套技术解决方案给公司带来的价值,在对它门复盘时候我们是这样评估的:
- 大表哥的价值:实现了公司数据报表量产的从 0 到 1,所谓量产,就是提效,提高数据报表从需求到上线的效率,进而提高业务方的决策效率,这个价值在过去的 2 年被充分证明了(有产品经理形容做报表比从起快了 8 倍,从起两三天,现在两三小时)
- 大盘子的价值:实现了公司报表及可视化的流程贯通,所谓贯通,就是降本,降低团队继续迭代报表和可视化的研发成本(基于原来的大表哥继续自研下去,研发成本会居高不下)
所以这个价值是一个递进关系的价值,在不同的阶段发挥能力,但不可否认,我们整个报表体系化建设中,的的确确走了弯路,多浪费了几个月的时间,半自研的启动其实可以更早更果断一些。
最后大家如果要做独立的报表系统,或者长出大盘可视化的能力,我们的建议依然是:
- 先驱动公司技术团队,建设好数仓,来接管复杂报表和大盘的多表计算需求,实时更新宽表
- 前端自研报表及可视化会有较高的成本,竞品调研再调研,能承担付费就用第三方过渡
- 魔改 Metabase 是一个不错的选择,前端至少要学习 Clojure,需要跨栈能力
基于前面的三波探索,我们目前明确的方向是,把大盘子和大表哥做融合,制作二维表/图表/编排大盘的能力都给到大盘子,数仓未建设到位的零碎报表展示由大表哥接管(会被逐步弱化但难以替代,因为高频的小报表需求是层出不穷的),同时 PC 端的大盘展示一律接入大表哥做展示,在大盘子和大表哥的背后,抽离连接数仓和其他 API 的能力,封装成微服务,同时供给大表哥和大盘子使用,以及将大表哥的导出服务也贡献给大盘子用,简而言之,大盘子上面制作,大表哥上面看,要透出到多端的时候,一律来嵌大盘子的大盘 URL 或者组件 SDK。
Scott 近两年无论是面试还是线下线上的技术分享,遇到许许多多前端同学,由于团队原因,个人原因,职业成长,技术方向,甚至家庭等等原因,在理想国与现实之间,在放弃与坚守之间,摇摆不停,心酸硬扛,大家可以找我聊聊南聊聊北,对工程师的宿命有更多的了解,有更多的看见与听见,Scott 微信: codingdream,也可以来 关注 Scott 语雀跟进最新动态,本文未经许可不许转载,获得许可请联系 Scott,否则在公众号上直接转载,尤其是裁剪内容后转载,我都会直接进行投诉处理。