如何实现动态指标实时计算 | FAAS实践

参考数仓分层的方式加工数据,一个业务指标大致流程如下:
image
层层推进,规范处理,就是资源多了些,流程长了些,然后它黄了。

回归原始,最直接的方式如下:
image
这样问题又来了,每次新指标过来,再到上线,周期太长了,资源是省了,效率就太低了,总结下想要的是这样了。
image

参考FAAS思路

Function 有两种机制,一种是完全按需,每个请求由独立的进程完成,一种是保持一种常驻的运行环境。前者我们称为 Exec 模式,后者我们成为 Runtime 模式。考虑资源和时间,只剩下Runtime可以参考。
在编程语法上,以 AWS 的 Javascript 的支持作为参考

exports.handler = (event, context, callback) => {
console.log('Received event:', JSON.stringify(event, null, 2));
var resp = {
        statusCode: '200',
        body: '{"msg":"hello"}',
        headers: {            'Content-Type': 'application/json',
        },        "isBase64Encoded": false,
    }    callback(null, resp);};

对程序猿来说这段代码好理解,不过动态配置的用户可就变成自身,无法脱离苦海了。简化是必然的,且这次只是为了做指标加工,那就编程直接体现出来好了。
custom_model(data1) / sum(data2) + avg(data3)

设计方案

image

● Master 包含一些模块:

  • Guard 统一信息入口,将信息传递给Dispatch,当保存完毕后,返回结果,确保信息不丢失。
  • Dispatch 负责获取并解析规则,指标依赖解析,状态保存与恢复。
  • Schedule 负责指标调度,以及Node状态维护等

● Node 获取数据源,执行计算,保存数据以及指标缓存,支持Node间直接读取缓存等
● MGR 配置规则,管理、监控展示等
● Work 监控进度,请求完成后执行报表回写,然后通知业务等

报文定义

基于TCP封装的报文比较常见,不过个人更喜欢UDP,再自定义个指标超时重试,就可以涵盖丢包问题,且速度更快,参考如下:
image

当Node重启后,通信信息可能不变,因此需要通过唯一键识别。用来重发指标和清空上报的Cache信息

指标范式

大部分基础指标的描述可以抽象为如下,比如商家去年全收入:
image

而复杂一些的指标,比如环比收入,可以拆分为两个指标再次计算,把指标的输出也当做数据对待,依然符合范式,参考流程如下:
image

基于此范式,我们就可以将黑盒 Function 细分为 DATA、Metric,这样就可以将IO 拆分出来,Function 主体分为两个部分:

  • DataHandler 只获取数据,不处理
  • MetricHandler 只计算,内部不涉及IO,输出结果

IO复用

大部分相关的指标使用的数据可能是一样的,因此当 NodeA获取数据后,会返回数据的相关信息给 Master。当 Master再度调度指标时候,填充数据缓存信息。当 NodeB想要获取数据时,则可以先从 NodeA获取,失败再从原始数据读取。

Metric基石

基于范式,如果我们可以提供常见的过滤和聚合(常见加工方式,比如某某模型),那么大部分指标都可以通过我们最初设想的表达式实现。而剩下的那些客户定制的特殊指标,先采用黑盒模式。当时基石越来越多,最终涵盖全部指标可配置。

原生优势

数据血缘

数仓中分析数据血缘是个不小的难题,解析SQL也无法实现100%。而基于指标范式的垂直领域中,IO与指标,指标与指标,之间的关系已经单独列出,直接读取即可,天然支持。

指标回溯

当我们想回溯一个指标,Metric是不会变的,那么关注的其实就是数据。Cache系统则是天然支持,同样归功于指标范式中IO与计算的分离。这里需要注意,我们不可能对所有数据都缓存太长时间。假设我们只关注出错指标,那么Node在处理指标时候,如果指标出错,则把依赖的数据的有效期变长(或者输出到指定存储,缓存有效期不变)。

其他话题

1.是否可以更快?

对相同的指标来说,当数据一样,计算耗时应该是一样的。因此当海量指标过来,采用数据粘性调度到对应的节点上,速度会更快一些。可以在 Schedule上通过分析 Cache信息,自定义一个调度即可。

2.UDP分包?

Master-Node 报文大小是可以控制的,不涉及分包。不过P2P进行数据传输必然涉及分包,在自定义的P2P报文中,需要实现报文的拆分与组装。(这里采用了简化,只要在指定时间内未收到请求回应的 P2P报头和所有 P2P报文,则直接丢弃,认为失败即可。)

posted @ 2023-01-30 11:37  last_coding  阅读(410)  评论(0编辑  收藏  举报