Что представляет собой ограничение по количеству запросов (rate limit) в API?

Привет всем! У меня возникла проблема с пониманием того, что такое Rate Limit при работе с API. В принципе, я осознаю, что это, но на практике ситуация не соответствует моим ожиданиям. Я разрабатываю свой первый проект, связанный с криптовалютами, и отправляю запросы к бирже Mexc для получения orderbook для каждого символа. Вот мой скрипт: <pre><code class="python">import asyncio
import json
import aiohttp


counter = 0

async def get_symbols(session):
    symbols = []
    async with session.get('https://api.mexc.com/api/v3/defaultSymbols') as response:
        data = await response.json()
        for i in data['data']:
            if 'USDT' in i:
                symbols.append(i)
    return symbols


async def get_orderbook(session, symbol, semaphore):
    global counter
    orderbook = {}
    async with semaphore:
        async with session.get(f'https://api.mexc.com/api/v3/depth?symbol={symbol}&amp;limit=10') as response:
            await asyncio.sleep(10)
            counter +=1
            print(response.status, counter)
            try:
                data = await response.json()
                if 'asks' in data and 'bids' in data:
                    asks = data['asks']
                    bids = data['bids']
                    orderbook[symbol] = {
                        'a': asks,
                        'b': bids
                    }
                    return orderbook
            except aiohttp.ContentTypeError as e:
                print(e)


async def main():
    async with aiohttp.ClientSession() as session:
        symbols = await get_symbols(session)
        tasks = []
        symbols_len = len(symbols)
        counter = 0
        semaphore = asyncio.Semaphore(100)
      
  • 24 декабря 2024 г. 19:23
Ответы на вопрос 2
Ограничение по количеству запросов (rate limit) — это механизм, который контролирует, сколько запросов клиент может отправить к API в определённый период времени. Это необходимо для защиты сервера от чрезмерной нагрузки, предотвращения злоупотреблений и обеспечения справедливого распределения ресурсов среди пользователей.

Основные аспекты работы с rate limit:

1. **Практическое применение**: Многие API устанавливают лимиты на количество запросов в минуту, час, день и так далее. Эти лимиты могут варьироваться от 1 запроса в секунду до нескольких тысяч запросов в минуту в зависимости от API и уровня доступа пользователя.

2. **Статусы ответов**: Когда вы превышаете лимит, API часто возвращает статус код 429 (Too Many Requests), что означает, что вы превысили разрешенное количество запросов.

3. **Информация о лимитах**: Часто API предоставляет информацию о текущем состоянии лимитов в заголовках ответа. Например, вы можете видеть заголовки, такие как `X-RateLimit-Limit` (максимальное количество запросов), `X-RateLimit-Remaining` (количество оставшихся запросов) и `X-RateLimit-Reset` (время сброса лимита).

### Как это применимо к вашему коду:

В вашем скрипте есть несколько моментов, которые стоит учесть в свете rate limiting:

1. **Отслеживание запросов**: Вы используете глобальный счетчик `counter`, чтобы отслеживать количество выполненных запросов. Но для более надежного контроля вам предпочтительнее использовать механизмы обработки ограничений на уровне API.

2. **Тайм-ауты и паузы**: В вашем коде вы добавили `await asyncio.sleep(10)`, что задерживает выполнение каждого запроса на 10 секунд. Это может помочь избежать превышения лимита, но не является идеальным решением. Вы должны выяснить точные лимиты API, чтобы оптимизировать паузы между запросами.

3. **Semaphore**: Вы используете семафоры для ограничения количества параллельных запросов, что хорошо. Но вам нужно дополнительно иметь населенную систему обработки ошибки 429, чтобы если вы получаете этот код, вы могли динамически зависнуть на время и попробовать снова.

### Пример обработки rate limit:
Если API возвращает статус 429, вы можете добавить обработчик ошибок, чтобы приостановить выполнение и повторить запрос через определенный промежуток времени:

```python
async def get_orderbook(session, symbol, semaphore):
    orderbook = {}
    async with semaphore:
        async with session.get(f'https://api.mexc.com/api/v3/depth?symbol={symbol}&limit=10') as response:
            if response.status == 429:
                print("Rate limit exceeded. Waiting before retrying...")
                await asyncio.sleep(60)  # Ожидание перед повторной попыткой
                return await get_orderbook(session, symbol, semaphore)  # Повторный запрос
            # Обработка успешного запроса
            try:
                data = await response.json()
                if 'asks' in data and 'bids' in data:
                    asks = data['asks']
                    bids = data['bids']
                    orderbook[symbol] = {
                        'a': asks,
                        'b': bids
                    }
                    return orderbook
            except aiohttp.ContentTypeError as e:
                print(e)
```

С этим подходом вы сможете более эффективно обрабатывать ограничения на количество запросов и избегать случаев, когда ваш код рушится из-за превышения лимитов.
Не понимаю зачем async , код максимально синхронный, ещё и с глобальными переменными. 

Возьмите готовые решения, например pymexc .
Похожие вопросы