策略编排
sequence 和 fallback 定义请求如何进入分支、调用子链并在主备路径之间切换。
sequence
作用
把多个 matcher 和 executor 编排成一条流水线,是最常用的入口执行器。
配置示例
- tag: seq_main
type: sequence
args:
# 先尝试读取缓存
- exec: "$cache_main"
# 命中缓存后直接结束
- matches: "has_resp"
exec: "accept"
# 多个 matches 写成数组时是逻辑与
# 示例里尽量直接写 quick setup 表达式
- matches:
- "client_ip $lan_ip_set"
- "qname $local_domains"
exec: "$hosts_main"
# 没有前置条件时也可以直接执行观测类插件
- exec: "$metrics_main"
# 还没有响应时再继续转发
- matches: "!has_resp"
exec: "$forward_main"
# 响应回来后统一收敛 TTL
- matches: "has_resp"
exec: "$ttl_main"
配置项
sequence 的 args 为规则数组,数组中的每个元素代表一条顺序执行规则。
args
- 类型:
array;必填:是;默认值:无 - 作用:定义 sequence 的规则链。
- 运行影响:
- 规则按书写顺序依次执行。
args为空时插件初始化失败。
args[].matches
- 类型:
string或array - 必填:否
- 默认值:无
- 作用:定义当前规则的匹配条件。
- 支持形式:
- 单个 matcher 字符串
- 多个 matcher 组成的列表
- 运行影响:
- 多个条件之间为逻辑与关系。
- 未配置时表示无前置匹配条件。
args[].exec
- 类型:
string;必填:否;默认值:无 - 作用:定义规则命中后要执行的动作。
- 支持内容:
- 插件引用
- quick setup 表达式
- 内建控制流
- 运行影响:
- 直接决定当前规则的执行行为。
行为说明
- 按顺序执行规则。
- 一条规则里多个
matches需要同时为真。 - 可以通过
jump/goto调用其它sequence。
内建控制流
sequence.args[].exec 除了调用插件,也可以直接写内建控制流:
accept
- 立即结束当前
sequence。 - 这是一次明确的提前停止,因此外层不会继续执行后续规则。
- 不会自动生成响应;通常用于前面已经有 response 的场景。
return
- 立即结束当前
sequence,并把控制权交回调用方。 - 不会自动生成响应。
- 若当前
sequence是被jump调用的,调用方会从下一条规则继续。
reject [rcode]
- 立即生成响应并结束当前
sequence。 - 默认
rcode为REFUSED。 - 支持十进制数值和大小写不敏感的英文 RCODE 名称,例如
reject 2、reject SERVFAIL、reject servfail、reject NXDOMAIN;常见映射与含义见 DNS 编码速查表。 - 只支持基础 DNS RCODE
0..15;扩展 RCODE 需要 EDNS OPT,不会由该内建动作自动生成。 reject 0返回普通NOERROR响应,不会自动附加 SOA。- 会中断后续规则,不再继续执行。
mark ...
- 写入一个或多个整数 mark,然后继续当前
sequence的下一条规则。 - 支持
mark 1、mark 1 2 3、mark 1,2,3。
jump seq_tag
- 调用另一个
sequence,语义类似子过程调用。 - 参数必须是目标
sequence的 tag,不能写$。 - 目标
sequence跑到尾部或执行return后,当前sequence会继续下一条规则。 - 如果目标
sequence执行accept/reject/ 其它Stop,当前sequence也会停止。
goto seq_tag
- 把控制权单向转交给另一个
sequence。 - 参数必须是目标
sequence的 tag,不能写$。 - 一旦执行
goto,当前sequence就不会再回到后续规则。 - 若目标
sequence执行return,该return会继续向外层传播。
典型用途
- 统一总入口。
- 把缓存、本地应答、转发、联动拆分成可读的策略层。
- 通过 marks、matchers 做复杂分支。
注意事项
- 被引用的插件必须已经定义。
sequence至少需要一条规则。
fallback
作用
在主路径失败或过慢时,切换到备用路径。
配置示例
- tag: fallback_main
type: fallback
args:
# 首选路径
primary: "forward_fast"
# 兜底路径
secondary: "forward_stable"
# 主路径超过 200ms 后允许备用路径接管
threshold: 200
# 让备用路径始终并行待命,换取更低尾延迟
always_standby: true
配置项
primary
- 类型:
string;必填:是;默认值:无 - 作用:指定主执行器。
secondary
- 类型:
string;必填:是;默认值:无 - 作用:指定备用执行器。
threshold
- 类型:
integer;必填:否;默认值:0 - 单位:毫秒
- 作用:定义主路径超时或延迟判定阈值。
always_standby
- 类型:
boolean;必填:否;默认值:false - 作用:控制备用路径是否与主路径同时待命。
short_circuit
- 类型:
boolean;必填:否;默认值:false - 作用:控制在主/备路径选出最终响应后,是否立即停止后续 executor 链。
行为说明
- 正向启动主路径。
- 到达阈值或主路径失败后启动/释放备用路径。
- 谁先拿到有效响应,谁赢。
- 另一分支会被取消。
- 开启
short_circuit时,胜出分支写回响应后会直接结束后续 executor 链。
Metrics
通过全局 GET /api/metrics 导出:
fallback_primary_totalfallback_primary_error_totalfallback_secondary_total
典型用途
- 快速上游 + 稳定上游的双层回退。
- 不同协议上游之间的故障兜底。
注意事项
- 这是“路径级”回退,不是“记录级”合并。
always_standby可以降低尾延迟,但会放大上游开销。