Вопрос или проблема
Я сталкиваюсь с проблемой ограничения скорости в своем коде на Python, хотя использую несколько прокси и обеспечиваю, чтобы каждый прокси вызывался только один раз. Тем не менее, я продолжаю получать ошибку: “Превышен системный уровень ограничения скорости.”
Вот общий обзор моей настройки:
У меня есть список прокси, и я использую каждый прокси только для одного запроса, каждый прокси вызывается только один раз (но с использованием потоков для одновременных запросов).
Однако после нескольких запросов я все равно получаю ошибку ограничения скорости.
Вот упрощенная версия моего кода на Python:
def _request(self, method, uri, timeout=5, auth=True, params=None):
uri_path = uri
data_json = ''
if method in ['GET', 'DELETE']:
if params:
strl = []
for key in sorted(params):
strl.append("{}={}".format(key, params[key]))
data_json += '&'.join(strl)
uri += '?' + data_json
uri_path = uri
else:
if params:
data_json = json.dumps(params)
uri_path = uri + data_json
headers = {}
if auth:
now_time = int(time.time()) * 1000
str_to_sign = str(now_time) + method + uri_path
sign = base64.b64encode(
hmac.new(self.secret.encode('utf-8'), str_to_sign.encode('utf-8'), hashlib.sha256).digest())
if self.is_v1api:
headers = {
"KC-API-SIGN": sign,
"KC-API-TIMESTAMP": str(now_time),
"KC-API-KEY": self.key,
"KC-API-PASSPHRASE": self.passphrase,
"Content-Type": "application/json"
}
else:
passphrase = base64.b64encode(
hmac.new(self.secret.encode('utf-8'), self.passphrase.encode('utf-8'), hashlib.sha256).digest())
headers = {
"KC-API-SIGN": sign,
"KC-API-TIMESTAMP": str(now_time),
"KC-API-KEY": self.key,
"KC-API-PASSPHRASE": passphrase,
"Content-Type": "application/json",
"KC-API-KEY-VERSION": "2"
}
headers["User-Agent"] = "kucoin-python-sdk/"+version
url = urljoin(self.url, uri)
proxy_dict = {'http': self.cl_proxy, 'https': self.cl_proxy} #if self.cl_proxy else None
#print (url,proxy_dict)
if method in ['GET', 'DELETE']:
r = requests.request(method, url, headers=headers, timeout=timeout, proxies=proxy_dict)
else:
r = requests.request(method, url, headers=headers, data=data_json, timeout=timeout, proxies=proxy_dict)
if ("System-level rate limit exceeded"):
s = str(url) + str(self.key)+ str(proxy_dict ) + str(r.status_code)
print (s)
Ответ или решение
Проблема, с которой вы столкнулись, связана с ограничениями по частоте запросов (rate limits), действующими на уровне системы, и, несмотря на использование множества прокси и постраничный подход к их вызову, вы по-прежнему получаете ошибку "System-level rate limit exceeded". Давайте разберемся, как решить эту проблему.
1. Понимание ограничений по частоте
Во-первых, необходимо понимать, как работает система ограничений по частоте на стороне API. Некоторые API применяют не только ограничение по идентификатору пользователя или IP-адресу, но и по системе в целом. Это означает, что если несколько пользователей или процессов работают с одного и того же сервера, ваши запросы могут быть ограничены.
2. Использование времени ожидания между запросами
Даже если вы используете разные прокси для каждого запроса, вы можете превышать общее ограничение по частоте. Попробуйте добавить время ожидания (например, используя time.sleep()
) между запросами. Это может помочь вам избежать превышения лимитов:
import time
def _request(self, method, uri, timeout=5, auth=True, params=None):
time.sleep(1) # Добавление ожидания в 1 секунду перед каждым запросом
...
3. Регулировка параллелизма
Если вы запускаете много потоков, которые выполняют запросы одновременно, это может привести к быстрому превышению лимитов. Попробуйте уменьшить количество одновременных запросов или использовать библиотеку, такую как concurrent.futures
, чтобы контролировать количество параллельных запросов:
from concurrent.futures import ThreadPoolExecutor
def send_requests(urls):
with ThreadPoolExecutor(max_workers=5) as executor: # Уменьшите количество потоков
executor.map(self._request, urls)
4. Логи и диагностика
Отслеживайте, какие именно запросы вызывают ошибку. Вы можете улучшить отладочные логи, добавив больше информации о статусе запроса и проверьте код ответа.
5. Понимание ограничения API
Проверьте документацию API, который вы используете. Возможно, существуют ограничения не только на количество запросов в минуту, но и на другие параметры (например, общий размер запросов). Некоторые API позволяют вам запросить временные квоты или предоставить более высокую квоту для платных пользователей.
6. Обработка ошибок и повторный запуск
Необходимо также реализовать обработку ошибок и повторный запуск запросов после определенного времени, если возникла ошибка превышения лимитов:
def _request(self, method, uri, timeout=5, auth=True, params=None):
retries = 5
for attempt in range(retries):
...
r = requests.request(method, url, headers=headers, timeout=timeout, proxies=proxy_dict)
if r.status_code == 429: # Код ошибки при превышении лимита
wait_time = 2 ** attempt # Увеличиваем время ожидания с каждым повтором
print(f"Rate limit exceeded. Waiting {wait_time} seconds before retrying...")
time.sleep(wait_time)
continue # Повторяем запрос
break # Если запрос успешен, выходим из цикла
Заключение
Все эти меры могут помочь уменьшить вероятность возникновения проблемы с превышением лимитов. Следите за частотой запросов и корректируйте параметры вашего кода в зависимости от ответов API. Также имеет смысл рассмотреть возможность перехода на платный тариф, если таковой предусмотрен и ваш проект это оправдывает.