关注点四:流量限制
Telegram 对你的 bot 每秒钟能发送多少条信息进行了限制。 这意味着你的任何 API 请求都可能会出现错误,并显示状态代码 429(Too Many Requests)和 此处 规定的 retry
响应参数。 这随时都可能发生。
处理这些情况只有一种正确的方法:
- 等待指定的秒数。
- 重试请求。
幸运的是,有一个 插件 可以做到这一点。
该插件 非常简单。 它实际上只是暂停一段时间然后重试。 然而,使用它主要是有一个潜在假设:任何请求都可能很慢。 这意味着当你以 webhook 的方式运行你的 bot 时,不管你做什么,你都不得不使用一个队列,否则你需要配置自动重试插件并确保它不会花费太多时间,但这样一来你的 bot 可能会跳过一些请求。
确切的限制是什么
它们是未规定的。
处理它。
我们对关于你能处理多少请求有一些好想法,但确切的数字是未知的。 (如果有人告诉你实际限制,说明他们并不了解情况。) 这些限制并不是你通过尝试 Bot API 可以找出的硬性阈值。 相反,它们是根据你的 bot 的确切请求载荷、用户数量和其他因素变化的灵活约束,其中并非所有因素都是已知的。
以下是一些关于速率限制的误解和错误假设。
- 我的 bot 太新了,不会收到洪水等待错误。
- 我的 bot 没有足够的流量,不会收到洪水等待错误。
- 我的 bot 的这个功能使用得不够频繁,不会收到洪水等待错误。
- 我的 bot 在 API 调用之间留有足够的时间,所以不会收到洪水等待错误。
- 这个特定的方法调用不会收到洪水等待错误。
get
不会收到洪水等待错误。Me get
不会收到洪水等待错误。Updates
所有这些都是错误的。
让我们来看看我们 确切 知道的事情。
关于速率限制的安全假设
从 Bot FAQ 中,我们知道有一些限制是不能超过的。
“在特定聊天中发送消息时,请避免每秒发送多于一条消息。我们可能允许短暂突发超过此限制,但最终你将开始收到 429 错误。”
这点应该很清楚。自动重试插件会为你处理这个问题。
“如果你要向多个用户发送批量通知,API 不会允许每秒超过 30 条左右的消息。为获得最佳结果,请考虑将通知分散在 8-12 小时的较长时间间隔内。”
这仅适用于批量通知,即主动向多个用户发送消息。 如果你只是回复用户的消息,则每秒发送 1000 条或更多消息都没有问题。
当 Bot FAQ 提到你应该 “考虑将通知分散在较长时间间隔内” 时,这并不意味着你应该添加任何人为的延迟。 相反,这里的主要要点是发送批量通知是一个需要花费很多个小时的过程。 你不能期望立即同时向所有用户发送消息。
“还要注意,你的 bot 每分钟无法向同一群组发送超过 20 条消息。”
同样,非常清楚。 这完全与批量通知或群组中发送的消息数量无关。 并且同样,自动重试插件会为你处理这个问题。
限流
有些人认为遇到速率限制是不好的。 他们更愿意知道确切的限制,以便可以对他们的 bot 进行限流。
这是不正确的。 速率限制是用于洪水控制的有用工具,如果你采取相应的措施,它们不会对你的 bot 产生任何负面影响。 也就是说,遇到速率限制不会导致封禁。 忽视它们才会。
而且,根据 Telegram 的说法,知道确切的限制是“无用和有害”的。
无用 是因为即使你知道限制,你仍然必须处理洪水等待错误。 例如,Bot API 服务器在维护期间关机重新启动时返回 429。
有害 是因为如果你为了避免达到限制而人为延迟某些请求,你的 bot 的性能将远非最佳。 这就是为什么你应该始终尽快发送请求,但要尊重所有的洪水等待错误(使用自动重试插件)。
但是,如果限制请求是不好的,那么如何进行广播呢?
如何进行消息广播
可以采用非常简单的方法进行广播。
- 向用户发送一条消息。
- 如果收到 429 错误,则等待并重试。
- 重复。
不要添加人为的延迟。 (这会使广播速度变慢。)
不要忽视 429 错误。 (这可能导致封禁。)
不要同时发送多条消息。 (你可以同时发送非常少量的消息(可能是 3 条左右),但这可能难以实现。)
上述列表中的步骤 2 由自动重试插件自动完成,代码如下所示:
bot.api.config.use(autoRetry());
for (const [chatId, text] of broadcast) {
await bot.api.sendMessage(chatId, text);
}
2
3
4
5
这里有意思的部分是 broadcast
是什么。 你需要将所有聊天记录存储在某个数据库中,并且需要能够缓慢地获取它们。
目前,你必须自己实现此逻辑。 将来,我们想创建一个广播插件。 我们很乐意接受你的贡献! 从这里 加入我们。