摘要 GB28181 故障模式繁多,厂商实现各异。GBDoctor 用 YAML 声明式规则库,将诊断知识从代码中解耦,支持社区贡献与持续沉淀。本文解析规则引擎的设计与实现。
如果每个故障都写死在 Go 代码里:
新增规则要改代码、重新编译
社区无法贡献
厂商差异难以维护
规则库的目标:让诊断知识可积累、可版本化、可社区化。
一条规则包含:
rule id: REG-401-ALGO category: register severity: blocking trigger: condition: "registerresponse.status == 401 && register_request.auth.algo != platform.auth.algo" title: "Digest 算法不匹配" evidence:
explain: > 平台要求 SM3,设备使用 MD5,认证必然失败。 advice:
vendor_notes: hikvision: "配置→网络→高级→平台接入→认证算法" dahua: "主菜单→网络→平台接入→GB28181→摘要算法" 字段说明:
rule_id:唯一标识,按类别前缀
category:register / keepalive / catalog / invite / rtp / ptz / cascade / gb2022
severity:blocking / warning / advice
trigger.condition:表达式,引擎求值
explain:人话解释
advice:修复建议列表
vendor_notes:厂商配置路径
GBDoctor 没有引入重量级表达式引擎,而是用 Go 的 text/template + 自定义函数,或简单的 DSL。为了性能,实际实现采用预编译的 Go 表达式:
type Condition func(ctx *DiagContext) bool
func compileCondition(expr string) (Condition, error) { switch expr { case "register_response.status == 401": return func(ctx *DiagContext) bool { return ctx.RegisterResp.Status == 401 }, nil // ... } } 更通用的做法是用 govaluate 或 expr 库,但为了零依赖,GBDoctor 选择手写常用条件。规则文件中的 condition 字符串在加载时映射到函数。
启动时扫描 rules/ 目录:
func LoadRules(dir string) ([]Rule, error) { var rules []Rule err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if strings.HasSuffix(path, ".yaml") { var r Rule data, _ := os.ReadFile(path) yaml.Unmarshal(data, &r) rules = append(rules, r) } return nil }) return rules, err } 诊断过程中,每个阶段结束后调用:
func MatchRules(stage Stage, ctx *DiagContext) []Issue { var issues []Issue for _, r := range rulesByCategory[stage] { if r.Condition(ctx) { issues = append(issues, Issue{ RuleID: r.RuleID, Severity: r.Severity, Title: r.Title, Explain: r.Explain, Advice: r.Advice, Vendor: r.VendorNotes, }) } } return issues }
vendor_notes 是规则库的核心价值之一。同一个问题,不同厂商配置路径不同:
vendor_notes: hikvision: "配置→网络→高级配置→平台接入→视频通道编码ID" dahua: "主菜单→网络→平台接入→GB28181→通道编码" uniview: "网络→平台接入→GB28181→通道编码" 报告生成时,根据设备 Manufacturer 字段匹配对应路径,直接展示给用户。
规则文件格式公开,社区可提交 PR。官方审核后合并,随版本发布。规则库独立于主程序更新,支持在线拉取或离线包。
声明式规则引擎让 GBDoctor 的诊断知识可积累、可扩展。代码负责协议与编排,YAML 负责故障模式与修复建议——这是工具越用越准的关键。
项目地址 Gitee:suoten/GBDoctor GitHub:suoten/GBDoctor 搜不到?在 Gitee 或 GitHub 搜索:GBDoctor 或 suoten GBDoctor
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050062/viewspace-3183210/ ,如需转载,请注明出处,否则将追究法律责任。