最近外卖服务出现过几次问题。一个下单接口超时时,值班同学需要先判断是否为自身服务的问题,再逐层排查下游依赖是否异常。当前主要通过监控平台中的单条曲线查看指标;服务数量增加后,调用链中的异常位置不易直接定位。
外卖团队需要一个整体查看服务运行情况的视图:将服务调用关系绘制为一张图,同时展示 QPS、调用方向和调用量。具体要求如下:
- 每个服务是一个节点,颜色按当前 QPS 高低变化,QPS 越高越红
- 服务之间的调用画成连线,线的颜色和粗细按调用 QPS 变化,调用越多线越红越粗
- 连线上要有沿调用方向移动的白点,表示调用方向
- 整体是一张有向图,节点位置由布局算法自动计算
前三项将指标映射为视觉属性;最后一项需要自动布局有向拓扑图,并在图上运行方向动画。
现有方案的限制
先看了公司里现成的图表方案,之前云盘用 echarts 做过点击热力图,echarts 的图表类型挺全,但热力图那一档是给地图或者矩阵用的,拓扑图不在里面,它没有”节点+连线+自动布局”这种图。
又找了几个开源的图表库,大多分两类。一类是柱状图、饼图、折线图这些”数据图表”库,根本没有拓扑图的概念。另一类是流程图/组织架构图工具,节点和连线有了,但布局基本是手动摆或者树形层级摆,不支持像力学模拟那样自动把节点铺开,更不用说线上跑动画点这种效果。
看到几个提到”力导向图”(force-directed graph)的例子,画的效果跟我们要的很像,几个都是基于 D3.js 做的。查了一下 D3,官网例子里正好有一个多对多关系的力导向布局 demo,节点会自动散开,连线会自动排布,不会挤在一起。这个方向是对的,但这些 demo 都是静态的,没有方向箭头,也没有沿线跑动的点,颜色映射也只是演示用的固定几档,QPS 这种连续数值要自己接比例尺进去。
调研结果是:没有现成方案同时覆盖这些需求。D3 提供数据绑定、坐标计算和图形生成等底层能力;节点颜色、方向动画等具体视觉规则仍需自行实现。
实现前需要掌握的 D3 能力
此前只零散使用过 D3,未系统了解数据绑定、比例尺和布局算法。实现大盘前,需要先验证这些能力并整理为可复用的代码。
学习顺序是按大盘需要的能力反推的:
- 选择集与数据绑定:
d3.select/selectAll怎么和 jQuery 的”选中元素改属性”区分开,数据条数变化时增删节点的 enter/update/exit 模式是怎么回事。节点和连线都是数据绑定出来的 DOM 元素。 - 比例尺与 SVG 图形基础。
d3.scale.linear()怎么把 QPS 的数值范围映射到像素或者颜色,d3.scale.ordinal()怎么给分类数据分配位置,顺带确认一下 SVG 的坐标系和常见的画反坑点。 - 力导向布局与方向动画。
d3.layout.force()具体怎么配置,节点位置怎么靠力学模拟一步步迭代出来(没有公式能一次算出来),箭头怎么用 SVG 的<marker>画,沿线移动的小白点怎么用定时器手写插值实现。
这三块笔记我分别整理成了三篇文章,放在这篇后面,感兴趣的话可以按顺序看:
大盘示意
这些代码分别处理数据绑定、QPS 到颜色和半径的映射、力导向布局,以及通过箭头和移动点表示方向。组合后的示意如下:
图中“订单核心”节点的 QPS 和被调用次数最高,因此颜色最红;从“下单”到“订单核心”的连线最粗、最红,表示该调用链路的调用量最大。白点沿调用方向移动。用户、对账等节点的调用量较小,颜色偏蓝且连线较细。
后续实现了一个 demo。数据为模拟数据,视觉映射与布局逻辑按上述四项要求实现,节点支持拖拽:
可单独打开 demo 页面查看。拖动节点时,连线、箭头和白点会使用节点的当前坐标更新;“订单核心”和“下单网关”之间的连线最粗、最红,白点速度也最高,因为速度按调用 QPS 映射;对账服务颜色偏蓝、连线较细。
尚未完成的工作
三篇 D3 笔记里写的都是孤立的小例子,节点数量、数据格式都是我自己编的。从这些小例子到能上线的大盘,中间还差三块工作。
第一是数据接入。QPS 和调用关系能从监控平台查到,但监控平台给的是原始指标,得自己写一层转换,整理成 nodes/links 这种 D3 布局能直接吃的数组格式,这块转换逻辑还没写。第二是刷新策略。监控数据不是毫秒级的,大盘多久拉一次新数据、拉到之后是整个重新跑一次力导向布局,还是只更新颜色和线宽、节点位置不动,这两种做法给人的感觉完全不同,得实际跑一下再定。第三是性能。笔记里试的都是十几个节点,外卖真实的服务数量比这个多不少,tick 回调里每帧都要重算所有节点和连线的坐标,节点一多会不会跟不上,只能拿真实数据量实测。
接口和数据模型确定后,才能验证大盘在真实服务规模下的刷新策略与性能。
