Rate limiting

Природа ограничений и причины появления rate limiting

Rate limiting в контексте Mapbox GL JS представляет собой совокупность механизмов, ограничивающих частоту сетевых запросов и вычислительную нагрузку, возникающую при работе с картографическими данными. Эти ограничения существуют одновременно на стороне клиента (браузера) и сервера (поставщика тайлов и API).

Ключевые источники нагрузки:

  • загрузка векторных и растровых тайлов
  • запросы к стилям (Style JSON)
  • обращения к sprites и glyphs (шрифты)
  • выполнение динамических запросов (queryRenderedFeatures, getSource, filter update)
  • пересчёт рендеринга при изменении состояния карты

Rate limiting в Mapbox GL JS не является единственным централизованным механизмом; он формируется комбинацией API-лимитов Mapbox, ограничений браузера и внутреннего планировщика запросов библиотеки.


Архитектура запросов и точки возникновения лимитов

Mapbox GL JS использует асинхронную модель загрузки ресурсов. Каждый слой карты может инициировать собственные сетевые запросы:

  • vector tiles (.pbf)
  • raster tiles (.png, .jpg)
  • style JSON
  • glyph ranges (PBF-based fonts)
  • sprite images and metadata

Каждый из этих типов ресурсов подчиняется отдельным ограничениям:

  • лимит параллельных HTTP-запросов на домен (обычно браузерный: 6–10 соединений)
  • лимиты Mapbox API (токен, тарифный план)
  • внутренний request scheduler библиотеки

В результате rate limiting проявляется не как единый throttle, а как совокупность задержек в pipeline загрузки карты.


Ограничения API Mapbox

На уровне сервиса Mapbox применяются ограничения:

  • количество запросов к тайлам в секунду
  • количество активных загрузок на токен доступа
  • ограничения по тарифному плану (free, pay-as-you-go, enterprise)
  • ограничения на геокодинг и дополнительные API

При превышении лимитов сервер может возвращать:

  • HTTP 429 Too Many Requests
  • временные блокировки токена
  • деградацию качества ответов (fallback tiles)

Mapbox GL JS автоматически повторяет некоторые запросы, но не снимает фундаментальное ограничение API.


Внутренний request scheduler

Mapbox GL JS использует очередь запросов, которая регулирует:

  • приоритет видимых тайлов (viewport priority)
  • отмену невидимых запросов
  • дедупликацию одинаковых ресурсов
  • ограничение параллелизма

При изменении viewport (pan, zoom, rotate) система пересчитывает приоритеты:

  1. Тайлы в текущей области экрана получают максимальный приоритет
  2. Тайлы вне экрана могут быть отменены
  3. Новые запросы вставляются в очередь ожидания

Этот механизм снижает вероятность перегрузки сети и уменьшает количество ненужных запросов.


Дедупликация запросов

Одним из ключевых механизмов защиты от превышения лимитов является дедупликация:

  • одинаковые tile requests (z/x/y) объединяются в один запрос
  • несколько слоёв могут использовать один и тот же источник тайлов
  • повторные обращения к glyph ranges кешируются

Это существенно снижает сетевую нагрузку при сложных стилях с большим количеством слоёв.


Кеширование как форма rate limiting

Кеширование в Mapbox GL JS выполняет функцию естественного ограничителя частоты запросов:

  • HTTP cache браузера
  • in-memory cache тайлов
  • persistent cache (в некоторых конфигурациях)

Типы кешируемых данных:

  • векторные тайлы
  • растровые тайлы
  • glyphs (шрифты)
  • sprites

Эффект кеша:

  • снижение количества повторных запросов
  • уменьшение нагрузки на API
  • ускорение повторного рендеринга одинаковых областей

Ограничение частоты рендеринга

Mapbox GL JS использует WebGL рендеринг с внутренним throttling кадров:

  • рендеринг синхронизирован с requestAnimationFrame
  • изменения состояния карты агрегируются в один цикл
  • несколько последовательных setState операций объединяются

Это предотвращает:

  • избыточный redraw при быстром pan/zoom
  • каскадные перерисовки слоёв
  • перегрузку GPU

Debounce и throttle пользовательских операций

Хотя библиотека не предоставляет явного API throttle, разработчики часто реализуют его поверх событий:

  • move → debounce
  • zoom → throttle
  • render → наблюдение без постоянной реакции

Типичный паттерн:

  • обработка события moveend вместо move
  • обработка zoomend вместо zoom
  • агрегация вызовов setFilter, setPaintProperty

Это снижает количество триггеров, ведущих к новым tile requests.


Ограничение параллельных загрузок

Браузер накладывает фундаментальные ограничения:

  • ограничение числа TCP соединений к одному домену
  • приоритет HTTP/2 multiplexing
  • очередь запросов при перегрузке

Mapbox GL JS учитывает эти ограничения:

  • не отправляет бесконечное число параллельных tile requests
  • управляет concurrency pool
  • перераспределяет загрузку по приоритетам

Обработка HTTP 429 и retry стратегия

При получении HTTP 429 система может:

  • повторить запрос через backoff
  • отменить второстепенные запросы
  • переключиться на cached tiles

Типичная стратегия retry:

  • exponential backoff
  • jitter для распределения нагрузки
  • ограничение числа повторов

Важно, что агрессивный retry может ухудшить ситуацию, усиливая перегрузку API.


Контроль нагрузки через transformRequest

Функция transformRequest позволяет вмешиваться в поток запросов:

  • добавление кастомных заголовков
  • маршрутизация запросов через прокси
  • логирование частоты обращений
  • фильтрация ненужных ресурсов

Используется для:

  • централизованного кеширования
  • ограничения доступа к определённым слоям
  • снижения количества внешних запросов

Оптимизация стилевой сложности как метод снижения rate limiting

Сложность стиля напрямую влияет на частоту запросов:

  • большое число слоёв увеличивает число tile requests
  • выражения фильтров увеличивают CPU load
  • частые layout changes вызывают re-evaluation источников

Методы оптимизации:

  • объединение слоёв
  • использование source-layer вместо множества источников
  • упрощение выражений фильтрации
  • уменьшение количества символов и label layers

Влияние vector tiles на нагрузку

Vector tiles являются наиболее чувствительным элементом к rate limiting:

  • каждый zoom level требует новых наборов тайлов
  • pan вызывает поток новых координатных запросов
  • высокая плотность данных увеличивает размер запросов

Оптимизации:

  • уменьшение maxzoom
  • генерализация данных на сервере
  • использование clustering для точек

Система приоритетов тайлов

Mapbox GL JS использует многоуровневую систему приоритетов:

  • High priority: видимая область экрана
  • Medium priority: adjacent tiles (preloading)
  • Low priority: off-screen cache candidates

Это позволяет:

  • снизить пиковую нагрузку
  • ускорить отображение при перемещении
  • избегать ненужных запросов при быстром навигационном движении

Географическое масштабирование нагрузки

Нагрузка запросов зависит от:

  • плотности данных в регионе
  • количества активных слоёв
  • уровня zoom

На низком zoom:

  • меньше тайлов
  • выше вероятность кеширования

На высоком zoom:

  • больше уникальных тайлов
  • выше вероятность превышения лимитов

Практики предотвращения rate limiting

Используются следующие стратегии:

  • предварительная загрузка критических областей
  • ограничение частоты обновления источников
  • использование clustered sources для точек
  • минимизация dynamic style updates
  • контроль частоты вызовов setData

Диагностика и мониторинг

Для анализа rate limiting применяются:

  • Network tab браузера
  • Mapbox telemetry (если включено)
  • логирование tile requests
  • измерение render time
  • анализ 429 ошибок

Ключевые метрики:

  • requests per second
  • failed tile loads
  • cache hit ratio
  • render frame time

Поведение при деградации сети

При ограничениях или нестабильной сети Mapbox GL JS:

  • использует частично загруженные тайлы
  • отображает fallback tiles
  • сохраняет последний валидный кадр
  • снижает частоту повторных запросов

Это обеспечивает устойчивость визуализации даже при активных лимитах API или нестабильном соединении.