惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Recent Announcements
Recent Announcements
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
有赞技术团队
有赞技术团队
J
Java Code Geeks
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
人人都是产品经理
人人都是产品经理
aimingoo的专栏
aimingoo的专栏
U
Unit 42
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 三生石上(FineUI控件)
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美
腾讯CDC
I
InfoQ
GbyAI
GbyAI
博客园_首页

程序员

V2EX 看到讨论"跨域"的帖子,那个她好像回来了 codex 今天真的是不稳定呀。 火山方舟 Coding Plan 慎买 刚问了大家 openclaw 和 hermes 在什么机器上面玩,求推荐一个机器 GPT-image-2 生成 AI 图片防伪有感 codex pro 5 小时限制已经严重缩水 逆天 Antigravity 动态 JSON 序列化对强类型语言很难吗? 自建了 GPT Coding Plan,遇到了定价问题,请教大家 大家都是在什么设备上玩 openclaw 以及 hermes 的呀? 软考还有一个月就考试了,你们学习了吗? 大伙用 AI 会考虑在 user scope 的 CLAUDE.md/AGENTS.md 里交代 AI 说中文吗 我发现程序员这个群体很大部分其实挺抠的 最近使用 cc 总会莫名其妙的返工, codex 不会 目前体验最好的远程 vibe 工具 想知道大佬们抓包遇到 ssl pinning 都是咋优雅的 解决的? 工业软件的大佬们是怎么 vibe coding 的 最近 chrome 是不是有 bug 啊,一搜索就卡住 分布式异步系统在 vibe coding 下的困境 PHP Native AOT 编译器,支持将 PHP 代码编译为可执行文件,运算性能提高 150 倍 没想到 2026 年,还要浪费大量时间在跨域问题上 DeepSeek V4 这周会出吗? 中转站正式试营 欢迎试用 不掺不假 小米 mimo 升级 v2.5,并且重置了额度 Jenkins, SCM 轮询完全不工作是啥问题啊 赛博斗蛐蛐, AI 模型的简单对比(白嫖版) 使用中转站要擦亮眼睛!不说别的,倍率计算 充值好乱。 买了火山的 Coding Plan 测试得出计费模式 给我的 AI 生成了简历和状态卡, 大家帮忙看下 Ta 能找到啥样的
关于 API 限流:令牌桶到底怎么写才稳?
matters · 2026-06-04 · via 程序员

最近在重构一套多策略的量化执行层逻辑,又绕不开 Rate Limit 这个问题。分享一点在生产环境实现平滑令牌桶( Token Bucket )时的经验:

1. 为什么弃用定时器?

早期写限流,直觉是用 Ticker 每隔一段时间加 Token 。

但当你的系统需要维护几百个交易对、几千个独立桶时(尤其是在处理多账号或多币种权重不同时),系统上下文切换和定时器开销会变得非常显著。

——优化点: 改用延迟计算。

不用主动去加 Token ,而是在 Request 到达时,根据 CurrentTime - LastRequestTime 动态计算。这样即便你有 10,000 个桶,不活跃的桶也不会占用任何 CPU 。

2. 重视“权重( Weight )”

有的交易所 API 文档里,限流单位往往不是“请求次数”,而是“权重值”。

  • 下单:5 weight

  • 查深度:2 weight

  • 批量撤单:10 weight

所以在设计令牌桶接口时,consume() 方法必须强制带上 weight 参数。如果你的限流器还停留在 count++阶段,在实战中基本没法用。

3. 处理网络抖动( Jitter )带来的假限流

理论上本地限流 10 次/秒,API 限制也是 10 次/秒,但因为网络抖动的存在,请求可能在某一毫秒“堆叠”到达服务端。

——避坑经验: 本地限流一定要比官方文档**保守 5%-10%**。同时,要在封装层实现一个简单的指数退避,捕获到 429 后立即收紧本地阈值,而不是死磕。

4. Python 示例

以下是抽象出来的一个最小原型,去掉了繁琐的业务逻辑,核心就是原子操作和延迟计算:

import time
import threading

class AllTickLimiter:
    def __init__(self, capacity: float, rate: float):
        """
        :param capacity: 桶容量(最大允许的突发请求权重)
        :param rate: 令牌恢复速率(每秒恢复的权重数)
        """
        self.capacity = float(capacity)
        self.rate = float(rate)
        self.tokens = float(capacity)
        self.last_tick = time.monotonic()
        self._lock = threading.Lock()

    def allow(self, weight: float = 1.0) -> bool:
        """
        检查当前令牌是否足够支付本次请求的权重
        """
        with self._lock:
            now = time.monotonic()
            # 1. 延迟计算:计算自上次请求以来生成的令牌
            delta = (now - self.last_tick) * self.rate
            self.tokens = min(self.capacity, self.tokens + delta)
            self.last_tick = now

            # 2. 尝试消费
            if self.tokens >= weight:
                self.tokens -= weight
                return True
            return False

    def sync_from_header(self, server_remaining: float):
        """
        利用响应头中的权威剩余量进行校准
        防止本地计算与服务端由于网络延迟导致的偏差
        """
        with self._lock:
            # 强制同步服务端返回的剩余额度
            self.tokens = min(self.capacity, server_remaining)
            self.last_tick = time.monotonic()

# --- 实战调用示例 —

# 假设你的 API 套餐是每秒 10 个 Token
limiter = AllTickLimiter(capacity=20, rate=10)

def get_market_data(symbol: str):
    # 假设查询实时报价权重为 1
    weight = 1.0
    
    if limiter.allow(weight):
        # 模拟 AllTick API 请求
        # response = requests.get(f"https://api.alltick.co/v1/quote?symbol={symbol}")
        # data = response.json()
        
        print(f"[{symbol}] 请求成功")
        
        # 进阶操作:从 Header 获取服务端权威数据进行同步
        # remaining = float(response.headers.get("X-RateLimit-Remaining", 20))
        # limiter.sync_from_header(remaining)
    else:
        print(f"[{symbol}] 触发本地限流,请求被拦截")

# 模拟快速并发请求
for i in range(15):
    get_market_data("BTCUSDT")

5. 分布式下的抉择

如果是单机策略,上面的逻辑足够。如果是多机集群,建议直接上 Redis + Lua 脚本。千万不要在分布式环境下尝试用各节点同步变量的方式做限流,一致性带来的延迟抖动会很折磨。