我正在開發一個帶有模塊pyTelegramBotAPI的bot,它通過webhooks與安裝的Flask + Gunicorn作爲webhooks的服務器一起工作。 Gunicorn正在與5名工人爲更好的速度,我的項目的結構看起來像這樣:電報bot的API速率限制
app.py
bot.py
在bot.py我有處理更新的功能:
def process_the_update(update):
logger.info(update)
update = types.Update.de_json(update)
bot.process_new_updates([update])
在app.py我進口這個函數,所以,每當更新到來時,app.py都會調用這個函數,bot將處理更新。在我的機器人用戶可以調用一個命令,它將使用外部API來獲取一些信息。問題是,這個外部API每秒限制3個請求。我需要配置一個具有這樣的速率限制的機器人。首先,我想用隊列的代碼做這樣的:
lock_queue = Queue(1)
requests_queue = Queue(3)
def api_request(argument):
if lock_queue.empty():
try:
requests_queue.put_nowait(time.time())
except queue.Full:
lock_queue.put(1)
first_request_time = requests_queue.get()
logger.info('First request time: ' + str(first_request_time))
current_time = time.time()
passed_time = current_time - first_request_time
if passed_time >= 1:
requests_queue.put_nowait(time.time())
lock_queue.get()
else:
logger.info(passed_time)
time.sleep(1 - passed_time)
requests_queue.put_nowait(time.time())
lock_queue.get()
else:
lock_queue.put(1)
first_request_time = vk_requests_queue.get()
logger.info('First request time: ' + str(first_request_time))
current_time = time.time()
passed_time = current_time - first_request_time
if passed_time >= 1:
requests_queue.put_nowait(time.time())
lock_queue.get()
else:
logger.info(passed_time)
time.sleep(1 - passed_time)
requests_queue.put_nowait(time.time())
lock_queue.get()
result = make_api_request(argument) # requests are made too by external module.
return result
的邏輯是,因爲我以爲,由於模塊pyTelegramBotAPI使用更快的更新線程處理,所有線程會檢查requests_queue,這將有充足的時間3最後api_requests,所以3個請求中的第一個請求的時間將與當前時間進行比較(以檢查是否通過了第二個時間)。而且,因爲我需要確定,只有一個線程會同時進行這種比較,所以我做了lock_queue。 但是,問題在於,首先,gunicorn使用5名工作人員,所以總會有可能性,來自用戶的所有消息將在不同的進程中處理,並且這些進程會有自己的隊列。其次,即使我將工人數量設置爲默認值(1名工人),我仍然得到429錯誤,所以我認爲,我的代碼不會按我想要的那樣工作。
我想用redis做速率限制,所以每次在每個線程和進程中bot都會檢查最近3次請求的時間,但我仍然不確定,這是正確的方式,我不確定,如何寫這個。
會很高興,如果有人提出任何意見或(外部API不提供任何的x限速頭)