跳到主要内容
版本:3.10.x

内置变量

API7 网关中的内置变量是可以在配置中直接引用的预定义变量。它们通常用于插件配置、路由匹配和日志自定义。

API7 网关支持三种类型的内置变量:

  • NGINX 变量
  • APISIX 变量
  • 自定义变量

这些变量按照特定的顺序进行求值。

NGINX 变量​

NGINX 提供了一组变量,用于获取请求和响应信息。

常用的变量包括:

变量描述
upstream_addr上游服务器的 IP 地址和端口,或 UNIX 域套接字路径。
remote_addr客户端地址。
request_method请求方法,如 GET 或 POST。
request_uri完整的原始请求 URI,包含参数。
server_name接受该请求的服务器名称。
status响应状态。在 NGINX 确定响应状态之前,它可能是 000。请在响应阶段的场景中使用,例如调试会话的采样规则或日志插件;不要用于路由匹配。
uri当前规范化后的请求 URI,在请求处理过程中可能发生变化。
http_user_agentUser-Agent 请求头的值。

有关更多信息,请参阅 NGINX 变量的完整列表。

APISIX 变量​

除了 NGINX 变量 之外,APISIX 还提供了各种内置变量:

变量名称描述
post_arg_*内容类型为 application/x-www-form-urlencoded 时的 HTTP POST 表单数据。星号将替换为 POST 表单数据的实际名称。
post_arg.*内容类型为 application/json、application/x-www-form-urlencoded 或 multipart/form-data 时的 HTTP POST 请求体参数。星号替换为 POST 参数的实际名称。支持类似 JSON Path 的选择器,如 post_arg.model.version 和 post_arg.messages[*].content[*].type。
arg_*URL 查询字符串。星号替换为实际的查询参数名称。
http_*HTTP 请求头。星号替换为实际的请求头名称。
cookie_*请求 Cookie。星号替换为实际的 Cookie 名称。
methodHTTP 请求方法,如 GET 或 POST。等价的 NGINX 变量是 request_method。
balancer_ip上游服务器 IP。
balancer_port上游服务器端口。
consumer_name消费者用户名。
consumer_group_id继承的消费者组 ID 运行时变量。API7 网关不会分配消费者组 ID,因此该变量未设置。
graphql_nameGraphQL 操作名称。
graphql_operationGraphQL 操作类型。
graphql_root_fieldsGraphQL 根字段。
route_id路由 ID。
route_name路由名称。
service_id服务 ID。
service_name服务名称。
resp_bodyHTTP 响应体。
mqtt_client_idMQTT 协议中的客户端 ID。
redis_cmd_lineRedis 命令。
rpc_timeRPC 请求往返时间。
external_user.*外部用户信息。openid-connect 等身份认证插件可以填充该变量,供其他插件使用。例如,当 key 设置为 ${external_user.preferred_username} 时,limit-count-advanced 可以按用户名执行限流。
upstream_unresolved_hostDNS 解析前配置的上游主机或域名(上游节点的 domain 或 host)。自 API7 企业版 3.9.15 起可用。
rate_limiting_info描述限流插件对本次请求判定结果的 JSON 对象。参见下文的限流信息。自 API7 企业版 3.9.6 起可用。
警告

http_* 读取的是 HTTP 请求头,它不是其他内置变量的前缀。例如 http_uri、http_method 和 http_status 读取的是名为 Uri、Method 和 Status 的请求头。请求路径、请求方法和响应状态应分别使用 uri、method 和 status。

API7 网关在编译表达式时不会校验这些请求头是否存在。如果客户端没有发送该请求头,依赖它取值的条件可能不会匹配,且不会报错。

限流信息​

rate_limiting_info 变量的值是一个 JSON 对象,描述限流插件对本次请求的判定。自 API7 企业版 3.9.6 起可用。

以下插件会设置该变量:limit-count、limit-count-advanced、graphql-limit-count 和 ai-rate-limiting。在这些插件运行之前,或在未配置这些插件的路由上,该变量为空字符串。

将变量写入访问日志​

在数据面的 config.yaml 中将该变量加入访问日志。将 access_log_format_escape 设为 json 后,该变量会以转义后的 JSON 字符串写入日志行:

conf/config.yaml
nginx_config:
http:
access_log_format: '{"time_local":"$time_local","remote_addr":"$remote_addr","request":"$request","status":"$status","rate_limiting_info":"$rate_limiting_info"}'
access_log_format_escape: json

先将日志行解析为 JSON,再将 rate_limiting_info 的值再解析一次 JSON。请按字段名读取字段:字段的顺序不固定。你也可以在日志类插件的日志格式中引用该变量。

计入固定窗口的请求,其变量值类似如下:

{"rate_limiting_key":"/apisix/routes/1:1:127.0.0.1","rate_limiting_limit":10,"rate_limiting_remaining":3,"rate_limiting_reset":42,"window_type":"fixed","window_size_ms":60000,"decision":"allowed","cost":1,"evaluated_at_ms":1759212345678,"current_window":{"start_ms":1759212300123,"end_ms":1759212360123,"count":7,"created":false}}

计入滑动窗口的请求,其变量值类似如下:

{"rate_limiting_key":"/apisix/routes/1:1:127.0.0.1","rate_limiting_limit":10,"rate_limiting_remaining":3,"rate_limiting_reset":14,"window_type":"sliding","window_size_ms":60000,"decision":"allowed","cost":1,"evaluated_at_ms":1759212345678,"current_window":{"id":29320205,"start_ms":1759212300000,"end_ms":1759212360000,"count":4},"previous_window":{"count":10,"weight":0.2387,"weighted_count":2.387}}

字段​

以下字段始终存在:

字段描述
rate_limiting_key本次请求所计入的计数器的键。
rate_limiting_limit窗口的配额。
rate_limiting_remaining本次请求之后的剩余配额。请求被拒绝或计数器无法更新时为 0。
rate_limiting_reset距配额重置的秒数,向下取整。滑动窗口拒绝请求时,该值是距离可以再次放行请求的时间,可能早于窗口结束时间。

以下字段描述本次请求所计入的窗口。自 API7 企业版 3.10.8 起可用。

字段描述
window_typefixed 或 sliding。
window_size_ms以毫秒表示的 time_window。
decisionallowed、rejected 或 error。error 表示计数器无法更新,例如 Redis 不可达。值为 error 时只包含上表中的四个字段,以及 window_type、window_size_ms 和 decision。
cost本次请求计入计数器的值。参见下文的计入值。
evaluated_at_ms判定本次请求的时间。
current_window.start_ms、current_window.end_ms当前窗口的起止时间。
current_window.count计入本次请求(含其 cost)之后当前窗口的计数。
current_window.created仅固定窗口。在开启该窗口的请求上为 true。
current_window.id仅滑动窗口。自 Unix 纪元以来的窗口序号。
previous_window.count、previous_window.weight、previous_window.weighted_count仅滑动窗口。上一个窗口的计数、对其应用的权重,以及两者的乘积。
delayed_sync仅延迟同步。参见下文的延迟同步。

所有 *_ms 字段都是以毫秒为单位的 Unix 时间戳或时长,取自网关实例的时钟。

不适用于该窗口类型或该配置的字段会被省略。适用但对本次请求未知的字段为 null。例如,使用 Redis 策略时 current_window.created 为 null;使用 local 策略的固定窗口拒绝请求时,current_window.count 为 null。

窗口类型​

固定窗口不与时钟对齐。它从该键下计入的第一个请求开始,在 time_window 秒后结束。使用 Redis 策略时,窗口结束时间由 Redis 计数器的 TTL 推算,不同请求之间可能相差几毫秒。

滑动窗口与时钟对齐。当前窗口从 current_window.id * window_size_ms 开始。当前窗口的计数,加上上一个窗口按其仍处于滑动范围内的比例加权后的计数,只要低于配额,请求就会被放行。previous_window.count 不超过配额,previous_window.weight 是该比例(0 到 1),previous_window.weighted_count 是两者的乘积。

计入值​

cost 是本次请求计入计数器的值,取决于请求的计数方式:

  • 固定窗口即使拒绝请求也会计入其 cost。
  • 滑动窗口只对放行的请求计数,因此被拒绝请求的 cost 为 0。
  • 延迟同步对两种窗口类型都只对放行的请求计数,因此被拒绝请求的 cost 为 0。

ai-rate-limiting 在转发请求之前检查配额,但该检查不计入本次请求,因此其 cost 为 0。它在响应之后再计入 token 数。

延迟同步​

Redis 策略配合 sync_interval 使用时,每个网关实例先在本地计数,每个间隔与 Redis 中共享的计数器同步一次。delayed_sync 对象描述本次请求判定时所依据的快照:

字段描述
delayed_sync.synced_at_ms该网关实例上一次同步计数器的时间。
delayed_sync.synced_count当时 Redis 中当前窗口的计数。
delayed_sync.local_delta该网关实例自那以后计入、尚未同步的值,不含本次请求。

计数和权重都是截至 synced_at_ms 的快照:

  • current_window.count 是估算值,即 synced_count + local_delta + cost,不包含其他网关实例自各自上次同步以来的计数。
  • 对于滑动窗口,current_window 和 previous_window 描述的是上一次同步时的窗口。previous_window.weight 是同步时确定的权重,也就是本次请求实际使用的权重,而不是 evaluated_at_ms 时刻的权重。
  • 每次同步都会替换快照。在窗口边界之后不久到达的请求,仍可能按上一个窗口的快照判定,因此它的 evaluated_at_ms 可能晚于 current_window.end_ms。

多条规则与多个插件​

该变量只保存一次判定。每次判定都会覆盖之前的值,因此该变量描述最后一条被判定的规则:

  • 插件配置了多条 rules 时,规则按顺序判定,遇到第一条拒绝请求的规则即停止。该变量描述这条规则;如果没有规则拒绝请求,则描述最后一条规则。
  • 一个请求上运行了上述多个插件时,该变量描述最后一个插件判定的规则。

求值顺序​

API7 网关按以下给定顺序对变量求值:

  1. 自定义变量
  2. APISIX 变量
  3. NGINX 变量

如果在自定义变量中成功获取到变量值,API7 网关将不再继续在 APISIX 变量或 NGINX 变量中查找。

换句话说,自定义变量将覆盖在 APISIX 变量或 NGINX 变量中定义的同名变量,以更好地满足你的特定用例需求。

变量语法​

有效的变量名称可以包含字母、数字、下划线(_)和句点(.)。

使用反斜杠(\)转义的变量不被视为变量,例如 \$variable_name。

简单格式和带括号格式​

变量可以通过两种格式进行引用:

  • $variable_name
  • ${variable_name}

这两种格式都受支持;然而,在某些上下文中需要带括号的格式以确保正确解析。

如果后面的字符不能作为变量名的一部分,无括号的 $variable 格式是有效的。例如,以下格式是等效的:

  • $http_host 与 ${http_host}
  • $arg_username-$arg_userid 与 ${arg_username}-${arg_userid}

当变量后跟一个可能属于变量名的字符(例如字母)时,解析器会将其错误地解释为较长的变量名。例如,对于 https://$http_baseurl.com,解析器会将整个字符串 http_baseurl.com 视为变量,这是不正确的。在这种情况下,你应该使用带括号的格式 https://${http_baseurl}.com 以清楚地界定变量。

如果你使用 ?? 运算符,你也需要带括号的格式。

使用 ?? 提供默认值​

你可以使用 ?? 运算符为变量指定默认值。如果该变量未定义,则使用运算符之后的值。

示例行为
${http_username ?? anonymous}如果 HTTP 请求头 username 有值则使用它;否则使用字符串 anonymous。
${http_count ?? 10}如果 HTTP 请求头 count 有值则使用它;否则使用字符串 10。