a6-plugin-fault-injection
概览
fault-injection 插件可以在 Apache APISIX请求处理中注入故障,包括延迟和 HTTP 中断,
该插件可用于混沌工程和弹性测试。它在 rewrite 阶段以 11000 的优先级(非常早)运行,因此会在包括身份认证和限流在内的大多数其他插件之前执行。
**执行顺序:**先执行 delay,再执行 abort。如果 abort 触发,则不会执行后续插件。
适用场景
- 混沌工程:模拟上游故障和响应变慢。
- 弹性测试:验证超时处理和熔断器行为。
- 负载测试:增加人为延迟以衡量性能下降。
- 灰度故障测试:针对特定用户或条件注入故障。
插件配置参考
必须至少指定 abort 或 delay 其中一项。
abort 对象
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
http_status | integer | 是 | — | HTTP 状态码(≥ 200) |
body | string | 否 | — | 响应体;支持 NGINX 变量($remote_addr) |
headers | object | 否 | — | 响应头;值支持 NGINX 变量 |
percentage | integer | 否 | 100(始终) | 触发中断的 请求比例(0–100) |
vars | array | 否 | — | 使用表达式语法的条件规则(最多 20 项) |
delay 对象
| 字段 | 类型 | 是否必填 | 默认值 | 说明 |
|---|---|---|---|---|
duration | number | 是 | — | 延迟时间(秒;支持小数,例如 0.5、1.5) |
percentage | integer | 否 | 100(始终) | 触发延迟的请求比例(0–100) |
vars | array | 否 | — | 使用表达式语法的条件规则(最多 20 项) |
vars 表达式语法
vars 字段使用逻辑表达式执行条件故障注入。
结构
[
[["condition1a"], ["condition1b"]], // AND group 1
[["condition2a"]] // AND group 2
]
// Groups joined by OR — first matching group triggers the fault
变量访问
| 前缀 | 来源 | 示例 |
|---|---|---|
arg_* | 查询参数 | arg_name → ?name=value |
http_* | 请求头 | http_apikey → X-Api-Key 请求头 |
| (无) | Nginx 内置变量 | remote_addr、uri、request_method |
运算符
| 运算符 | 示例 |
|---|---|
== | ["arg_name", "==", "jack"] |
~= | ["arg_env", "~=", "prod"] |
>, >=, <, <= | ["arg_age", ">", 18] |
~~ | ["arg_env", "~~", "[Dd]ev"](正则表达式) |
~* | ["arg_env", "~*", "dev"](不区分大小写的正则表达式) |
in | ["arg_ver", "in", ["v1","v2"]] |
! | ["arg_age", "!", "<", 18](否定 → >=) |
ipmatch | ["remote_addr", "ipmatch", ["10.0.0.0/8"]] |
分步示例
1. 固定延迟(3 秒)
a6 route create -f - <<'EOF'
{
"id": "delay-test",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"delay": {
"duration": 3
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
2. 按比例中断(50% 请求返回 503)
a6 route create -f - <<'EOF'
{
"id": "abort-test",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 503,
"body": "Service temporarily unavailable",
"percentage": 50
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
3. 基于查询参数的条件中断
仅在 ?name=jack 时触发中断:
a6 route create -f - <<'EOF'
{
"id": "conditional-abort",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 403,
"body": "Fault Injection!\n",
"vars": [
[["arg_name", "==", "jack"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
4. 复杂条件逻辑(AND/OR)
当满足 (name=jack AND age≥18) OR (包含 api-key 请求头) 时触发中断:
a6 route create -f - <<'EOF'
{
"id": "complex-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 403,
"body": "Fault Injection!\n",
"vars": [
[
["arg_name", "==", "jack"],
["arg_age", "!", "<", 18]
],
[
["http_apikey", "==", "api-key"]
]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
5. 使用 NGINX 变量设置自定义请求头
a6 route create -f - <<'EOF'
{
"id": "headers-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 200,
"body": "{\"uri\": \"$uri\"}",
"headers": {
"X-Fault-Injected": "true",
"X-Request-URI": "$uri"
}
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
6. 灰度故障测试
仅带有 X-Canary: true 请求头的用户会遇到 10% 的故障比例:
a6 route create -f - <<'EOF'
{
"id": "canary-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"abort": {
"http_status": 500,
"percentage": 10,
"vars": [
[["http_x_canary", "==", "true"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
7. 使用不同条件组合延迟和中断
a6 route create -f - <<'EOF'
{
"id": "combined-fault",
"uri": "/api/*",
"plugins": {
"fault-injection": {
"delay": {
"duration": 2,
"vars": [
[["http_x_slow", "==", "true"]]
]
},
"abort": {
"http_status": 503,
"vars": [
[["http_x_fail", "==", "true"]]
]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
配置同步示例
version: "1"
routes:
- id: fault-injection-demo
uri: /api/*
plugins:
fault-injection:
delay:
duration: 1
percentage: 25
abort:
http_status: 503
body: "Service unavailable"
percentage: 5
upstream_id: my-upstream
执行行为
- 先评估 Delay:如果 vars 匹配且比例抽样命中,则执行
sleep(duration)。 - 再评估 Abort:如果 vars 匹配且比例抽样命中,则立即返回。
- 比例抽样:
math.random(1, 100) <= percentage。 - abort 触发时:后续插件(认证、限流)会被跳过。
插件优先级说明
优先级 11000 表示 fault-injection 会非常早地运行:
- ✅ 链路追踪插件(zipkin、skywalking)可以捕获故障。
- ❌ 限流无法阻止故障。
- ❌ 身份认证无法阻止故障。
如需仅对已认证用户注入故障,请使用 vars 检查与认证相关的变量或请求头。
故障排查
| 现象 | 原因 | 解决方法 |
|---|---|---|
| 故障从未触发 | percentage: 0 或 vars 始终不匹配 | 检查 vars 表达式,并将 percentage 设置为大于 0 的值 |
| 故障始终触发 | 未设置 percentage(默认为 100%) | 将 percentage 设置为所需值 |
| 故障绕过认证 | 插件在认证之前运行(优先级 11000) | 使用 vars 限制故障作用域 |
| 请求体未插值 | 变量缺少 $ 前缀 | 在请求体/请求头中使用 $uri,而不是 uri |
| 延迟和中断都触发 | 先运行延迟,再运行中断 | 这是预期行为;延迟总是在中断检查之前执行 |
本文根据 api7/a6 仓库中的 a6-plugin-fault-injection/SKILL.md 生成。可在 AI Agent Skills 页面浏览全部 Skill。