6.1 代码开发规范


6.1 代码开发规范

本节摘要:DAG 代码是可执行的合同,规范要保证三件事:解析可重复且无副作用、运行可重放且幂等、人能在评审里看懂责任与窗口。命名、default_args、禁止顶层 IO、禁止密钥进库、doc_md 写清业务影响,是最低集。风格华丽不在检查单上。

读前必看(上)

阅读完本节,你应当能够:

  1. 写出一份团队可用的 DAG 审查清单
  2. 识别顶层 Variable 查询、模块级数据库连接等解析期毒药
  3. 为任务规定幂等写法:按窗口覆盖或按主键去重
  4. 用 tags 与 owner 把告警路由写进代码

一、解析期像纯函数

文件会被反复 import。模块顶层只应有 import、常量、DAG 构造。不要在顶层读 Variable、打开连接、请求 HTTP、扫描对象存储列目录。这些在解析循环里对元数据库和外部系统造成固定打击,DAG 数量一多,调度器先死。动态工厂若必须读配置,读本地静态清单或启动时缓存一次,并明确那不是运行时热更新。

允许顶层:import、常量、构造 DAG 对象 禁止顶层:Variable.get、数据库查询、网络、无限循环 运行时:任务函数内部

DAG id 稳定。改名等于新 DAG,旧历史不跟过去。用业务名加层名,不要加日期、不要加作者名。任务 id 短且稳定,TaskGroup 前缀要想好,以免日后无法对齐传感器。

default_args 在仓库里给一份推荐模板:owner、retries、retry_delay、execution_timeout。禁止每个文件自己发明一套重试 99 次。catchup 默认 False,需要补数写进变更说明并走 backfill。新 DAG 建议创建后暂停,等人点过检查再启动。

二、幂等、密钥、可读性

同一窗口跑两次,结果应收敛。入库用分区覆盖或合并。带副作用的外部工单(创建变更单)要按窗口去重。不能幂等的任务,重试就是加倍事故,应把 retries 降到 0 并人工处理,而不是假装坚韧。

密钥只通过 Connection 或运行时保险库。代码扫描应拒绝 password=、AK 字符串、私钥块。日志 print 连接对象同样拒绝。

doc_md 写:做什么、窗口如何切、失败影响谁、数据位置。tags 至少含环境与层级与是否关键。owner 必须是团队可路由名,不是已经离职的个人。

检查项 通过标准 失败典型样子
解析无 IO 顶层无 Variable/网络 import 即打数据库
catchup 默认 False 原点很早且 True
密钥 无明文 主机密码写在算子参数
幂等 重跑不双写业务 insert 无去重
时间 用区间不用 now 补数日错乱
依赖 边清晰,汇聚规则正确 分支后 all_success 卡死

三、结构与复用

复用通过包里的工厂函数生成同构任务,而不是复制粘贴三大段 SQL。工厂仍要在解析期便宜。TaskGroup 用于画布,不是用于藏秘密逻辑。跨 DAG 依赖写明对方 dag_id 与对齐规则,放进 doc_md。

Python 版本、Provider 版本与核心版本写在平台文档,DAG 作者不在文件里 pin 一套私有版本。需要额外库,走镜像变更,不走任务内安装。

⚠️ 常见坑:在函数默认参数里塞 datetime.now() 或可变列表。默认参数只求值一次,窗口会串味。
💡 关键直觉:规范不是为了好看。每一条都对应过一种生产事故:解析打库、补数打满、密码进 Git、重试双写。

代码量控制:一个文件一个 DAG,过大就拆。动态生成上千 DAG 的文件要有测试证明 id 唯一且数量有上限。没有上限的工厂,等于允许配置表把调度器炸了。

注释写“为什么这个 trigger_rule 不是默认”,不写“创建一个任务”。评审者需要的是偏离默认的理由。

与数据科学家协作时,给他们模板仓库(概念上,不给路径):已含 default_args、禁止清单、示例 TaskFlow。比课堂上讲架构快。模板要随平台升级改,旧 DAG 不必一次改完,但新 DAG 必须走新模板。

四、合并模板上的口头禅

评审人只问六句。顶层有没有 IO?catchup 是不是假?有没有明文秘密?同一窗跑两次会不会双写?owner 能不能路由到活人团队?偏离默认的 trigger_rule 有没有理由?六句都过,再看 SQL 美不美。美不美不进最低集。把最低集做成合并机器人能扫的部分加人工部分,机器人扫密钥和 Variable.get 顶层,人工看幂等和窗口。

模板仓库(概念上)提供:推荐 default_args、禁止清单注释、一条 TaskFlow 示例、一条专用算子示例、结构测试示例。新 DAG 必须从模板复制概念结构,而不是从上周某份生产 DAG 复制后改 id——后者会把 catchup 和错误规则一起传染。传染是规范失败的主要方式。

id 稳定性:对外被传感器或 Dataset 引用的 task_id 改名,要当破坏性变更,走通知。对内仅画布上的名字可以在同一发布里改,但仍要改测试断言。动态工厂的 id 规则写进测试:前缀、字符集、长度、唯一。配置表插入一行就能炸调度器的工厂,等于把生产解析权交给配置表作者,配置表作者也必须走规范。

与分析师协作:他们改 SQL,你改图。SQL 进可评审的字符串或外部定义,仍由 CI 跑结构测试。不要给他们 UI 编辑生产图的权限,见 5.2。规范是权限的补集:权限挡人,规范挡内容。

问题:旧 DAG 要不要一次性改到新模板?

不要。新 DAG 强制,旧 DAG 在触碰时改,关键 DAG 限期改。一次性迁移会制造超大差异,无法评审。规范的目标是停止出血,不是整容。

问题:email_on_failure=True 算规范吗?

在邮件后端没接好之前算反规范,它制造“以为有人会收到”的假安全感。接好了再开,且仍要有即时频道给关键 DAG。owner 字段比邮件开关更基础,因为回调和值班路由都靠它。

五、规范如何避免变成壁纸

每周抽两条新合并 DAG 对照六句口头禅,结果公开。只写文档不抽查,规范会在第三周死亡。机器人能扫的密钥和顶层 Variable 必须进 CI,人工只看机器人看不到的幂等与窗口。奖惩不要对人羞辱,要对合并:不合规范就打回,几次之后模板会自己流行。流行是因为省事,不是因为海报感人。owner 指向离职个人时自动失败结构测试,这比发邮件提醒有效。规范与测试章在此接头:规范条目若不能变成断言或抽查,就从最低集拿掉,免得条目膨胀到没人读。短而执行,长而忽略。

六、从生产 DAG 反推规范是否还活着

每月抽样看:新 DAG 是否仍从错误范本复制 catchup;owner 是否仍是个人昵称;顶层是否又出现 Variable.get。抽样结果若变差,规范已死,重启抽查而不是加长文档。加长文档是死亡加速。活着的规范会在结构测试里表现为红灯,而不是在 wiki 里表现为段落。把六句口头禅写成测试并不全部可能,但 catchup、retries 上限、owner 格式可以。能自动化的立刻自动化。不能的保持抽查。抽查名单公开。公开不是羞辱,是让范本市场自发切换到能过闸门的模板。自发切换是规范成功的唯一可持续形态。靠运动式整改,运动结束就回潮。回潮后的 Airflow 看起来像没有第 6 章。本教程把规范写成闸门,就是为了反对运动。运动累人,闸门烦人,烦人比累人更可值班。值班需要可重复,不需要高潮。

七、结构测试先覆盖的三个断言

catchup 为假、retries 不超过上限、owner 符合团队前缀。三条先写。写完就进 CI。进 CI 比完善文档优先。优先因为红灯会逼模板。模板会流行。流行会让六句口头禅里能自动化的部分真正落地。不能自动化的幂等与窗口,保持抽查。抽查公开。公开加红灯,规范才有两只手。一只机器,一只人。两只都在,壁纸化会慢。慢不等于不死。死的信号是抽样变差。变差就重启抽查频率,不加长 wiki。wiki 加长是死亡加速。加速来自以为文字等于执行。执行等于红灯加打回。打回来自三条断言。断言来自本节。本节把三条写成最低自动化。最低不是理想。理想会拖延。拖延让明文密码继续合并。继续合并一天,就多一天范本污染。污染用三条红灯先止血。止血后,再加密钥扫描。扫描在 CI 更前。更前是因为密钥比 catchup 更急。更急仍不替代三条。三条管时钟与责任。时钟与责任是 DAG 合同的骨架。骨架没有,密钥扫描只保证秘密的坏图也能进生产。也能进不是成功。成功是坏图进不去。进不去靠三条。三条先写。写的人是平台。用的人是作者。作者被红灯教育。教育比培训短。短而重复。重复是 CI。CI 是规范的身体。身体在 6.1 长出第一条肌肉。肌肉是三条断言。断言今晚就可以写。今晚写,明天红。明天红,后天模板改。后天模板改,下周抽样会好看。好看不是目的。目的是 catchup 不再为真。为真会抽干连接池。连接池在 3.1。3.1 怕 6.1 没有三条。有三条,库能喘。喘是规范的基础设施意义。意义不只是代码风格。风格稍后。稍后不是永远。永远稍后会壁纸。壁纸用抽样监控。监控变差就动手。动手是加频率不是加段落。段落结束。断言开始。开始三条。三条结束本节的最低集。最低集结束 6.1。6.1 把笔交给 6.2。6.2 在三条之外减负担。负担在解析。解析在顶层 IO。顶层 IO 也可扫描。扫描可后加。后加仍先三条。三条先。先结束。

八、密钥扫描放在三条之前

CI 顺序:密钥与顶层 Variable 扫描,然后 catchup、retries、owner 三条。秘密比时钟更急,但仍不替代三条。替代会让无秘密的坏时钟图通过。通过会抽干库。库怕 catchup。catchup 靠三条。三条靠今晚写。今晚写结束拖延。拖延结束范本污染。污染结束复制 True。True 结束遥远原点。原点结束事故配方。配方结束于红灯。红灯结束壁纸。壁纸结束加长 wiki。wiki 结束运动。运动结束。抽查加红灯两只手。两只手结束 6.1。6.1 结束风格优先。风格稍后。稍后结束永远。永远结束。最低集结束于扫描加三条。加三条结束今晚。今晚结束本节。

九、owner 个人昵称当场失败

结构测试用正则卡团队前缀,昵称进不了生产。进不了结束告警发到空气。空气结束。路由结束于前缀。前缀结束本节最后一断言。断言结束个人英雄。英雄结束系统值班。值班结束。前缀是合同上的收件人。收件人必须是团队。

本章回顾

  • 顶层无副作用 是调度器活着的前提
  • id 稳定,改名即新 DAG
  • catchup 默认关,幂等默认要
  • 密钥与日志扫描进评审
  • owner/tags/doc_md 是告警与治理接口
  • 复用走包与镜像,不走运行时装载

下一节在规范之上,处理解析、锁、XCom 和冷启动这些让集群变慢的真实原因。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U