开源工程管理,释放开发者潜能
介绍
Middleware是一款开源工具,旨在帮助工程领导者使用DORA 指标来衡量和分析团队的效率。DORA 指标包含四个关键值,可深入了解软件交付性能和运营效率。
它们是:
- 部署频率:代码部署到生产或运行环境的频率。
- 变更交付周期:从提交到最终投入生产环境所需的时间。
- 平均恢复时间:发生事故或故障后恢复服务所需的时间。
- 变更失败率:导致部署失败或需要补救的部署所占的百分比。
目录
本文探讨了Middleware公司基于规则的告警和通知系统的开发过程。该系统名为Playbook,旨在当某些指标超过预定义的阈值时通知客户。
我加入Middleware担任全职软件工程师后的首要任务之一,就是构建一个名为 Playbook 的东西。
该操作手册作为一个基于规则的警报系统,允许工程经理在特定指标超过设定阈值时收到通知。例如:
如果开发人员在过去一周内花费超过 50% 的时间用于修复错误,请发送电子邮件。
如果团队上个月的平均 PR 返工时间超过 6 小时,请发送 Slack 消息。
设置规则和频率:用户为其团队定义警报规则,并选择规则检查的时间范围。
违规处理:系统从数据库中读取规则,根据这些规则验证指标,并生成违规通知。
发送通知:根据用户设置的时区向其发送通知。
用户和团队等实体是存在的。
服务可以提供指定时间范围内用户或团队的指标值。
通知分发器可以通过 Slack/电子邮件发送通知。
每次违规行为仅发送一次通知。
该系统采用多种模型,包括剧本模型、剧本规则模型、剧本规则违规模型和通知模型。这些模型分别处理规则创建、违规事件生成和通知分发。
剧本核心:将剧本创建为规则的聚合体。每条规则都包含一些设置数据和执行频率。
违规处理程序:根据用户设定的规则和规则节奏识别违规行为。
通知处理器:根据违规行为创建通知。
通知分发器:通过不同渠道发送通知。
剧本和剧本规则:
战术手册是由球队经理制定的。
每个操作手册都针对每个指标制定了一系列规则,并设定了阈值。
class Playbook(){
team_id: uuid,
created_by: uuid,
created_at:date_time,
updated_at:date_time,
updated_by: uuid,
rules: set(PlaybookRule), (set hashes based on rule type),
}
class PlaybookRule(){
rule_type: PlaybookRuleType(ENUM),
rule_data: {}
alert_cadence: PlaybookRuleAlertCadence(ENUM),
users_to_notify: set(uuid),
is_active: boolean
}
class PlaybookRuleType(Enum):
CYCLE_TIME= "CYCLE_TIME"
INCIDENT_COUNT = "INCIDENT_COUNT"
提醒频率是指用户希望接收这些通知的频率。
每日频率:违规情况每日计算,我们根据用户时区每日发送通知。
每周频率:违规情况根据每周数据进行计算,通知于每周一发送。
两周一次:违规情况根据过去两周的数据进行计算,每隔一周的星期一发送通知。
按月频率:违规次数按月平均值计算,通知于每月 1 日发送。
class AlertCadence(Enum):
DAILY="DAILY"
WEEKLY="WEEKLY"
TWO_WEEKS="TWO_WEEKS"
MONTHLY="MONTHLY"
剧本泄露:
触发违规:每当指标超过或低于设定的阈值时,就会生成 PlaybookBreach。
关联:每个 PlaybookBreach 都与一个 playbook 和一个规则类型相关联,为违规行为提供上下文。
规则数据包含:为了适应未来可能的规则变更,每次违规事件都会包含生成时的规则数据。这确保了历史数据的准确性和一致性,即使未来的规则发生修改。
class PlaybookRuleBreach(){
playbook: uuid,
rule_type: uuid,
rule_data: {}
team_id: uuid,
alert_cadence: PlaybookRuleAlertCadence(ENUM),
metric_value: float
}
通知:
违规通知:一旦发生违规行为,即可生成通知并发送给用户。
防止重复:为避免重复通知,每个通知都分配一个幂等键,以确保数据库中的唯一性。
通知模型灵活性:该通知模型设计灵活,可兼容 Playbook 以外的其他服务。因此,每条通知都可以按类型分类,以便于组织和处理。
class Notification(){
receiver_id: uuid,
idempotency_key: str,
notification_type: NotificationTypes(ENUM),
due_at: date_time,
queued_at: date_time,
sent_at: date_time
}
本节将阐述如何使该系统具有鲁棒性:
即使系统发生故障,也要确保按设定的时间间隔可靠地生成违规报告。
采取措施防止产生重复违规行为。
建立保障措施,避免发送重复通知。
为通知开发重试机制,以应对程序错误或系统故障。
我们必须根据用户设定的节奏检查并处理我们的操作手册规则。
为此,我们可以简化系统,使用每天运行的 CRON 任务。
每次 CRON 作业执行时,都会按每日节奏处理流程规则。
检查当前日期是否为每月警报频率的规则的 1 号。
对于每周发出警报的规则,请在周一处理。
以两周为一个周期的警报频率处理规则,即在每月第一个或第三个星期一处理规则。
如果由于数据不正确、代码中未处理的情况或实体被删除而导致某个规则失败,那么在单个 cron 进程中处理所有这些数据可能会是一个挑战。
例如:如果您已处理了 10 条规则,但第 11 条规则存在未处理的案例,则最后生成的违规记录和通知将被浪费,不会存储到数据库中。同样,一旦 CRON 任务抛出错误,就需要手动重新触发,否则我们将不得不等待它下次自动运行。
为了避免这种情况,我们采用生产者-消费者模型。
将每个剧本规则视为一个单独的作业,并将这些作业排入剧本规则队列中。
利用多个工作进程监听 PlaybookQueue,并一次处理一个作业,以生成 PlaybookRuleBreach 和通知。
如果作业失败,队列将收到 500 状态码,我们可以设置一些警报,队列可以重新尝试执行此失败的作业。
使用非先进先出 (FIFO) 队列可确保在部署修复程序时,失败的作业不会阻塞队列。
关于技术选择:
所描述的系统在其内部系统中使用了 Amazon SQS 和 Lambdas。
虽然 AWS 为这种设置提供了内置功能,但也可以使用其他服务提供商或自定义解决方案来构建类似的系统。
一旦通知进入数据库,我们就可以运行一个每小时一次的 CRON 任务,检查数据库中是否有任何到期通知,并将它们作为作业排队。
这些通知任务由通知调度程序处理,该调度程序决定使用哪个通道来通知用户,并运行任何其他逻辑来操作为通知类型设置的通知消息。
数据在分布式系统中传输时,难免会出现故障。我们的设计考虑到了部分故障情况,但每个系统都有其自身的不足之处。
队列会重试因违规而失败的保存操作。
当保存通知失败并进行重试时,请确保不会针对同一数据包生成重复的违规事件。违规事件的判定结果应基于 playbook_id、rule_type 和规则检查间隔保持幂等性。
在重新排队执行剧本规则作业时,我们使用基于违规数据的幂等键来防止重复通知保存到数据库中。
利用幂等性密钥,我们确保可以从一次违规事件中生成一条通知。
如果已发送的通知失败,队列将进行重试。
如果已发送的通知被重新排队,工作进程将检查 sent_at 键以查找通知,确保它没有被重新发送。
如果用户在通知生成并等待发送后更新了规则,我们仍然会发送通知。
这是一个特殊情况,由于时间限制,我们没有在内部处理。
也可以通过将用于生成通知的违规行为中的规则数据与关联剧本中的规则数据进行交叉检查,然后删除通知并重新排队 PlaybookRule 作业来处理此问题。
过去一年,Middleware开发的基于规则的通知系统在我们目前的规模下已经证明了其稳健性。
虽然它可能不是目前最具扩展性的通知系统,但我希望这篇文章能给你一些启发 :)
开源工程管理,释放开发者潜能
Middleware是一款开源工具,旨在帮助工程领导者使用DORA 指标来衡量和分析团队的效率。DORA 指标包含四个关键值,可深入了解软件交付性能和运营效率。
它们是:
目录