从 0 到 1 搭建技术中台之报警平台实践:匹配器演进

本文介绍伴鱼内部服务报警平台中匹配器模块的演进,及其利用 Lex 和 Yacc 同类工具构建 DSL 编译器的过程 。
背景报警平台是伴鱼内部各端、应用、基础设施等服务异常状态信息的集散中心 。整体流程如下图所示:
从 0 到 1 搭建技术中台之报警平台实践:匹配器演进

文章插图
 
信息源将信息投递给报警平台,后者将这些信息最终通过邮件、即时消息、电话呼叫的形式路由给理应关心它的人 。总体而言,路由的需求可以分为以下几种:
  • 路由给服务的负责人及其团队
  • 路由给服务依赖方人员及其团队
  • 路由给所有值班人员所在的即时消息群
为了满足这样的需求,报警平台采用树状结构组织路由信息,如下图所示:
从 0 到 1 搭建技术中台之报警平台实践:匹配器演进

文章插图
 
每个节点是一个路由节点,节点上可以挂载不同的规则,如抑制规则、通知规则;也可以存放不同的配置信息,如触发报警的阈值,以及相关负责人及其团队的联系方式 。
根路由是所有异常信息的必经之路,经过这里的信息会路由给所有值班人员;一级子路由节点是所有的服务,经过这里的信息会路由给该服务的负责人及其团队;如果有其它团队想要订阅某服务的异常消息,如 Service A 团队想要了解 Service B 的崩溃 (panic) 信息,则可以在 Service B 节点下创建子路由 Service B Panic,并在上面配置 Service A 团队的联系方式,从而达到订阅目的 。
那么如何判断一条报警信息将经过哪些路由节点,一条规则是否起作用?这就需要引入本文的主角:匹配器 (matcher),每个路由、每条规则上都会挂载一个匹配器,当它成功匹配到报警信息时,路由和规则就会生效 。一条典型的报警信息会有许多信息,我们不妨将它看作是任意数量的键值对,如:
?复制代码
{"title": "Web 服务 ServiceB 崩溃报警 ","source": "192.168.0.1","error_type": "panic","project_name": "ServiceB","project_source": "web","details": "(call stack)",//...}我们可以试着写出路由节点 ServiceB 及 Service B Panic 的匹配器:
  • ServiceB:project_source 为 web 且 project_name 为 ServiceB
  • Service B Panic:project_source 为 web,且 project_name 为 Service B,且 error_type 为 panic
报警平台的用户需要亲自配置部分路由和规则,能否定制一套简单、易上手的 DSL?如:
?复制代码
project_source = "web" AND project_name = "ServiceB"这样即使用户不是工程师,看过几个例子后也能熟练地书写匹配表达式 。
匹配表达式定义匹配器表达式由原始表达式和复合表达式构成 。原始表达式是最小的匹配器,有完全匹配和正则匹配两种:
?复制代码
# 完全匹配project_source = "web"# 正则匹配details =~ "duplicate key when insert"原始表达式的左手边是报警信息的标签,不带双引号;原始表达式的右手边是匹配文本,带双引号 。不同的原始表达式可通过二元关系运算,AND (且) 和 OR (或) ,组合成复合表达式如:
?复制代码
project_source = "web" AND project_name = "ServiceB" OR "error_type" = "panic"类似于乘除之于加减,AND 的优先级大于 OR,如果要改变优先级,可通过增加括号来实现,如:
?复制代码
project_source = "web" AND (project_name = "ServiceB" OR "error_type" = "panic")编译过程一个完整的编译过程大致分三阶段:
从 0 到 1 搭建技术中台之报警平台实践:匹配器演进

文章插图
 
  1. 前端:验证源码的语法和语义,并解析成中间表述 (Immediate Representation, IR)
  2. 中端:针对 IR 作一些与目标 CPU 架构无关的优化
  3. 后端:针对目标 CPU 架构优化并生成可执行的机器指令
我们也可以将匹配器表达式理解成一门语言,但我们只需要将它转化成合理的内存数据结构即可,因此这里只涉及到完整编译过程的前端:
  1. 词法分析 (Lexical Analysis):将完整的语句拆成词语和标点符号
  2. 语法分析 (Syntax Analysis):根据语法规范,将词语和标点符合组合成抽象语法树 (AST)
  3. 语义分析 (Semantic Analysis):向语法树中添加语义信息,完成校验变量类型等各种语义检查


    推荐阅读