TensorZero 自定义限流(Rate Limiting)实战指南:基于 Valkey/Redis 后端的规则配置、优先级与作用域详解 TensorZero 自定义限流Rate Limiting实战指南基于 Valkey/Redis 后端的规则配置、优先级与作用域详解【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzeroTensorZero Gateway 内置了细粒度的自定义限流Custom Rate Limiting能力帮助你在统一的 LLM 网关层控制推理调用量、Token 消耗与成本支出。本文基于官方操作指南 Enforce custom rate limits 及配套可运行示例 valkey-redis 代码示例 展开讲解规则三大要素资源、优先级、作用域的语义并深入到 crates/tensorzero-core/src/rate_limiting 源码验证其实现原理。读完本文你将掌握在tensorzero.toml中编写多级限流规则、按用户标签实现总配额 单用户配额 白名单覆盖的完整方案并理解容量/补充速率capacity/refill_rate连续令牌桶模型的适用场景。限流规则的核心概念在 TensorZero 中限流规则定义在配置文件的[[rate_limiting.rules]]数组中一条配置可以包含多条规则。限流状态存储在独立的后端数据库Valkey 或 Postgres中因此Gateway 重启后已有配额会被保留多个 Gateway 实例之间也会自动共享同一套限流状态。每条规则由三个维度组成资源Resources限定什么如模型推理次数、Token 数、成本以及时间窗口每秒、每小时、每天、每周、每月。例如每天 1000 次模型推理每小时 50 万 Token每天 $10。优先级Priority当多条规则同时命中同一请求时决定哪条规则生效优先级数字越大越优先。作用域Scope限定规则应用于哪些请求可以设置全局限制也可以按自定义标签如user_id或 API Key 做定向限制。资源Resources与时间窗口每条规则可以包含一个或多个资源限制使用RESOURCE_per_WINDOW语法声明。例如[[rate_limiting.rules]] # ... model_inferences_per_day 1_000 tokens_per_second 1_000_000 cost_per_day 10.0 # ...可用的资源包括资源含义说明model_inferences模型推理次数每完成一次模型推理计数 1tokens消耗的 Token 数请求必须显式指定max_tokensToken 类限制才会生效cost成本美元以浮点数表示如10.0代表 $10.000.50代表 $0.50时间窗口是顺序且不重叠的即非滑动窗口对齐到每个限流桶首次初始化时刻。例如一个RESOURCE_per_minute规则若在 10:30:15 首次被使用则会在 10:31:15、10:32:15……依次重置。提示若请求涉及 Token 类限制必须指定max_tokens。Gateway 会先做合理保守的 Token 用量估算待请求结束后再记录实际用量见下文配额借还与归还。提示对于成本类限制Gateway 会先按可配置的default_cost默认 $1.00预估每请求成本请求完成后再依据 Provider 上报的实际成本调整已消耗预算。如果模型 Provider 不上报成本信息则维持默认估算值不做调整。因此只有在你已为相关模型 Provider 配置了成本信息时才应使用成本限流详见 Track usage and cost。在源码 crates/tensorzero-core/src/rate_limiting/mod.rs 中RateLimitInterval枚举定义了Second、Minute、Hour、Day、Week、Month六种窗口to_microseconds()方法将其转换为 Valkey Lua 脚本使用的微秒数其中Month被定义为恰好 30 天2,592,000,000,000 微秒而非日历月。作用域Scope按标签或按 API Key每条规则可以可选地指定scope将规则限定到特定请求不指定作用域则应用于所有请求。按标签tags限定可以用用户自定义的tags限定作用域支持三种取值方式具体值仅匹配该标签等于特定值的请求tensorzero::each独立作用于tag_key的每一个取值即每个取值各自独立计算配额tensorzero::total对所有取值合计计算配额。例如以下规则仅应用于标签user_id为intern的推理请求[[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value intern } ] #...若作用域包含多个条目则所有条目必须同时满足规则才生效。例如以下规则仅应用于user_id intern且env production的推理请求[[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value intern }, { tag_key env, tag_value production } ] #...tensorzero::each示例——每个user_id取值拥有独立配额[[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value tensorzero::each }, ] #...tensorzero::total示例——所有用户合计共享一份配额[[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value tensorzero::total }, ] #...警告上述规则不会应用于未指定user_id标签的请求tensorzero::total只统计带该标签的请求。按 API Key 限定启用认证后可以基于 API Key 限定作用域这对实现分级访问tiered access或防止单个 Key 消耗过多资源非常有用。支持两种取值tensorzero::each每个 API Key 独立计算配额具体的 12 位公共 ID只针对该 Key。例如以下规则让每个 API Key 各自独立限流[[rate_limiting.rules]] # ... scope [ { api_key_public_id tensorzero::each }, ] #...针对特定 API Key12 位公共 ID[[rate_limiting.rules]] # ... scope [ { api_key_public_id xxxxxxxxxxxx }, ] #...提示TensorZero API Key 格式为sk-t0-xxxxxxxxxxxx-yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy其中xxxxxxxxxxxx即 12 位公共 ID可在限流规则中使用其余部分为密钥必须妥善保管。与标签作用域不同API Key 公共 ID 作用域不支持tensorzero::total仅支持tensorzero::each与具体 12 位公共 ID。此外带api_key_public_id作用域的规则不会应用于未认证请求认证配置见 Set up auth for TensorZero。优先级Priority每条规则必须设置priority如priority 1。Gateway 从最高优先级开始逐级遍历规则直到找到匹配的限流一旦命中强制执行该优先级下的全部规则并忽略所有更低优先级的规则。例如以下配置对user_id intern的请求强制执行第一条规则优先级 1其余user_id值执行第二条规则优先级 0[[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value intern }, ] priority 1 #... [[rate_limiting.rules]] # ... scope [ { tag_key user_id, tag_value tensorzero::each }, ] priority 0 #...另外可以设置always true让规则无论其他规则如何都强制执行always true的规则不参与上述优先级计算。在源码 crates/tensorzero-core/src/rate_limiting/mod.rs 中RateLimitingConfig::get_active_limits的实现恰好印证了这一语义第一遍遍历所有规则收集匹配结果并找出最大优先级max_priority第二遍过滤时RateLimitingConfigPriority::Always的匹配规则无条件保留Priority(n)的规则只有在n max_priority时才保留。因此可以理解为always true是必选层priority是最优匹配层。搭建完整的可运行示例Valkey/Redis 后端官方在 examples/docs/guides/operations/enforce-custom-rate-limits/valkey-redis 目录下提供了完整可运行示例包含config/tensorzero.toml、docker-compose.yml、openai_sdk.py与pyproject.toml。下面按步骤展开。第一步部署限流后端限流需要一个后端存储二选一ValkeyRedis部署 Valkey 并设置TENSORZERO_VALKEY_URL环境变量部署指南见 Deploy Valkey / RedisPostgres部署 Postgres 并设置TENSORZERO_POSTGRES_URL环境变量部署指南见 Deploy Postgres。警告若同时设置了TENSORZERO_VALKEY_URL与TENSORZERO_POSTGRES_URLGateway 将使用 Valkey 进行限流。从源码层面看后端选择逻辑位于 rate_limiting_manager.rs 的new_from_connectionsbackend配置为Auto时按 Valkey → Postgres 的顺序选择显式指定Valkey/Postgres时若对应后端不可用则直接返回配置错误。注意该实现采用 fail-closed失败即关闭语义若限流后端不可用限流操作会返回错误并导致 Gateway 拒绝请求避免在后端宕机时向 LLM Provider 放行昂贵的流量。若配置了规则却没有可用后端会提示设置TENSORZERO_VALKEY_URL/TENSORZERO_POSTGRES_URL或将rate_limiting.enabled设为false。示例的 docker-compose.yml 给出了一个学习用途的完整栈生产环境请勿直接使用需参考 TensorZero Gateway 部署services: valkey: image: valkey/valkey:8 ports: - 6379:6379 volumes: - valkey-data:/data healthcheck: test: valkey-cli ping | grep -q PONG start_period: 30s start_interval: 1s timeout: 1s gateway: image: tensorzero/gateway volumes: - ./config:/app/config:ro command: --config-file /app/config/tensorzero.toml environment: TENSORZERO_CLICKHOUSE_URL: http://chuser:chpasswordclickhouse:8123/tensorzero TENSORZERO_VALKEY_URL: redis://valkey:6379 OPENAI_API_KEY: ${OPENAI_API_KEY:?Environment variable OPENAI_API_KEY must be set.} ports: - 3000:3000 depends_on: clickhouse: condition: service_healthy valkey: condition: service_healthy其中TENSORZERO_VALKEY_URL: redis://valkey:6379即把限流后端指向容器内的 Valkey 实例。Valkey 支持四种 URL 协议valkey://标准连接、valkeys://TLS 加密、redis://valkey://别名、rediss://valkeys://别名。TensorZero 启动时会自动向 Valkey 加载所需的 Lua 函数无需手动初始化。第二步配置限流规则将以下内容写入 config/tensorzero.toml随后重新加载 Gateway# [A] Collectively, all users can make a maximum of 1k model inferences per hour and 10M tokens per day [[rate_limiting.rules]] always true model_inferences_per_hour 1_000 tokens_per_day 10_000_000 scope [ { tag_key user_id, tag_value tensorzero::total } ] # [B] Each individual user can make a maximum of 1 model inference per minute [[rate_limiting.rules]] priority 0 model_inferences_per_minute 1 scope [ { tag_key user_id, tag_value tensorzero::each } ] # [C] But override the individual limit for the CEO [[rate_limiting.rules]] priority 1 model_inferences_per_minute 5 scope [ { tag_key user_id, tag_value ceo } ] # [D] The entire system (i.e. without restricting the scope) can make a maximum of 10M tokens per hour [[rate_limiting.rules]] always true tokens_per_hour 10_000_000这条配置演示了四类典型用法规则[A]全站硬性上限always true所有用户合计每小时最多 1000 次推理、每天最多 1000 万 Token规则[B]兜底的单用户配额priority 0每个用户每分钟最多 1 次推理规则[C]特权覆盖priority 1对user_id ceo的用户把每分钟上限提高到 5 次覆盖规则 [B]规则[D]无作用域的全局 Token 上限always true整系统每小时最多 1000 万 Token不区分用户。注意修改限流规则会重置其用量统计在规则配置之前产生的请求不计入限额。统计从规则首次应用到请求时才开始。第三步发起推理请求验证效果按上述配置若连续两次以user_id intern发起推理第二次应因规则 [B]每分钟 1 次而失败而连续两次以user_id ceo发起两次都应成功规则 [C] 覆盖规则 [B]。示例 openai_sdk.py 使用 OpenAI SDK 演示了这一行为——通过extra_body{tensorzero::tags: {user_id: user_id}}向 TensorZero 网关传递自定义标签from openai import OpenAI client OpenAI(base_urlhttp://localhost:3000/openai/v1, api_keynot-used) def call_llm(user_id): try: return client.chat.completions.create( modeltensorzero::model_name::openai::gpt-4.1-mini, messages[ { role: user, content: Tell me a fun fact., } ], max_tokens1000, extra_body{tensorzero::tags: {user_id: user_id}}, ) except Exception as e: print(fError calling LLM: {e}) # The second should fail print(call_llm(intern)) print(call_llm(intern)) # should return None # Both should work print(call_llm(ceo)) print(call_llm(ceo))示例的 pyproject.toml 声明了运行依赖openai2.3.0与tensorzero2025.10.1Python 客户端Python 版本要求3.10。说明若你更倾向于 Postgres 后端仓库还提供了同结构的 postgres 示例目录配置与调用方式一致仅后端环境变量不同。源码级原理配额如何被借出与归还限流不是简单的计数一次而是采用先预估借票、后按实际归还的两阶段模型。在 crates/tensorzero-core/src/rate_limiting/mod.rs 的模块注释中明确描述了整体流程调用方构造包含当前 Provider 请求信息的ScopeInfo携带tags与api_key_public_id见 ScopeInfo 定义调用RateLimitingConfig::consume_tickets先用ScopeInfo判定哪些限流作用域命中get_scope_keys_if_matches要求所有scope 条目同时匹配才返回 key见 Scope trait 实现然后保守地预估请求的资源消耗接着从数据库Postgres 或 Valkey实际消费票券返回TicketBorrows调用TicketBorrows::return_tickets用实际观测到的用量做事后记账补偿多借或归还少借的部分。关于保守预估源码 get_estimated_tokens 采用每 2 个字符约等于 1 个 Token的粗估上界对当今绝大多数 LLM 成立但并非硬性边界。这正是文档中先做合理保守估算、后记录实际用量的出处。归还阶段的精细化逻辑在 rate_limiting_manager.rs 的 return_tickets_inner 中若实际用量大于借用量则补扣差额consume_tickets若实际用量小于借用量且属于Exact精确用量则退还差额return_tickets若属于UnderEstimate如流式推理出错、Provider 未上报 Token 用量等无法确认实际用量的场景则即使看似多借也不退还以免错误地放行。成本类资源在真实成本未知时nano_cost None会跳过退还并给出警告日志建议为模型 Provider 配置成本以获得准确的成本限流。另一个值得注意的工程细节数据库以字符串key标识一条活跃限流key 由{resource, scope_key}序列化而来见 get_key 实现。如果两条不同规则的 key 相同会被视为同一条限流而互相覆盖trample因此开发者不应随意改动 key 的序列化方式也不要添加可能互相覆盖的 key。高级用法自定义容量与补充速率token bucket 连续补充模型默认情况下限流采用简单桶模型每个时间窗口开始时一次性重置全部容量。例如tokens_per_minute 100_000表示每分钟可用 100,000 Token每分钟初整额刷新。你可以通过capacity与refill_rate参数改为连续补充的令牌桶[[rate_limiting.rules]] # ... tokens_per_minute { capacity 100_000, refill_rate 10_000 } # ...capacity设定桶中可存储的最大令牌数refill_rate决定每个时间窗口向桶内补充的令牌数本例为每分钟 10,000。这样不会在每分钟开始一次性发放全部额度而是每分钟补充 10,000 Token、桶内最多囤积 100,000 Token。要发挥该模型优势通常应使用低时间粒度并让capacity远大于refill_rate。它特别适合突发保护用户无法在开头几秒耗尽全天配额流量平滑请求随时间自然摊开而不是集中在窗口边界更优体验用户获得稳定的配额涓流而不必苦等下一个时间窗口。在源码层面RateLimit结构体mod.rs 定义同时保存capacity与refill_rate二者通过ConsumeTicketsRequest/ReturnTicketsRequest一并下发给数据库执行见 ActiveRateLimit 的请求构造。在多 TensorZero 部署之间集中管理限流如果你有多个 TensorZero 部署例如每个团队一套可以通过Gateway Relay网关中继集中化限流。中继模式下一次 LLM 推理请求在到达模型 Provider 之前可依次经过多个相互独立的 TensorZero Gateway 部署从而在不限制团队构建方式的前提下执行组织级管控。详见 Centralize auth, rate limits, and more。Valkey 后端运维最佳实践针对使用 Valkey 的部署Deploy Valkey / Redis 还给出以下运维建议淘汰策略Eviction Policy限流是正确性问题——静默淘汰会重置限流状态、导致客户端超限缓存只是性能问题——淘汰仅造成一次缓存未命中。若用同一实例承载两者推荐volatile-ttl策略TensorZero 将限流 key 的 TTL 设为至少 48 小时对比缓存默认 24 小时 TTL内存压力下限流 key 最后被淘汰因此应确保缓存 TTL 小于 48 小时以维持正确的淘汰顺序。为缓存拆分专用实例可选默认限流与推理缓存共用TENSORZERO_VALKEY_URL。内存紧张时可设置TENSORZERO_VALKEY_CACHE_URL将缓存指向独立实例主实例限流配noeviction保证限流 key 永不被静默淘汰缓存实例配volatile-lru高效管理缓存。持久化Valkey 进程级故障如崩溃可能丢失上次备份以来的限流数据。若限流窗口很短分钟级一般可容忍若要求精确限额或窗口较长建议配置周期性的 RDB时间点快照以增强持久性。总结TensorZero 的自定义限流是一个声明式配置 两阶段借还记账的完整体系[[rate_limiting.rules]]负责声明资源、窗口、作用域与优先级Valkey/Postgres 后端负责跨实例共享限流状态always/priority配合tensorzero::each/tensorzero::total/ 具体值三级作用域足以组合出全站硬上限 单用户兜底 特权覆盖的生产级限流策略。配合 valkey-redis 可运行示例 与 postgres 示例你可以在几分钟内把整套方案跑起来并验证优先级语义。【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考