Квоты и биллинг

Система тарификации Mapbox основана не на количестве строк кода, а на фактическом использовании картографических сервисов платформы. При работе с Mapbox GL JS основным объектом биллинга выступают загрузки карты (Map Loads), а также обращения к дополнительным сервисам, таким как геокодирование, маршрутизация, статические изображения и наборы данных.

При создании экземпляра карты через объект mapboxgl.Map браузер начинает запрашивать необходимые ресурсы:

  • стиль карты (Style);
  • тайлы векторных или растровых данных;
  • шрифты и глифы;
  • иконки и спрайты;
  • данные источников (Sources).

Каждое такое использование может участвовать в расчёте стоимости в зависимости от выбранного тарифного плана и подключённых сервисов.

Простейшая инициализация карты выглядит следующим образом:

mapboxgl.accessToken = 'YOUR_TOKEN';

const map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v12',
    center: [37.6176, 55.7558],
    zoom: 10
});

После загрузки карты начинается взаимодействие с инфраструктурой Mapbox, которое фиксируется системой аналитики и биллинга.


Понятие Map Load

Map Load — основная единица тарификации при использовании Mapbox GL JS.

Под загрузкой карты обычно понимается создание нового экземпляра карты, который начинает получать ресурсы Mapbox.

Например:

const map1 = new mapboxgl.Map({
    container: 'map1',
    style: 'mapbox://styles/mapbox/light-v11'
});

const map2 = new mapboxgl.Map({
    container: 'map2',
    style: 'mapbox://styles/mapbox/dark-v11'
});

В приведённом примере создаются две независимые карты, что может быть учтено как две отдельные загрузки.

Особенности:

  • перезагрузка страницы обычно создаёт новую загрузку;
  • открытие карты в новой вкладке формирует отдельное использование;
  • создание нескольких экземпляров карты на одной странице увеличивает количество загрузок;
  • длительное взаимодействие с одной картой не приводит к появлению новых Map Load.

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


Access Token и связь с биллингом

Каждое приложение использует токен доступа.

Пример:

mapboxgl.accessToken = 'pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJhYmMxMjM0In0';

Токен позволяет:

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

Без корректного токена большинство сервисов Mapbox работать не будут.


Типы токенов

Mapbox поддерживает несколько типов токенов.

Public Token

Наиболее распространённый вариант для клиентских приложений.

mapboxgl.accessToken = 'pk.xxxxxxxxx';

Особенности:

  • доступен в браузере;
  • не считается секретным;
  • используется в большинстве веб-карт;
  • участвует в статистике использования.

Secret Token

Используется на серверной стороне.

Пример применения:

const token = process.env.MAPBOX_SECRET_TOKEN;

Особенности:

  • не должен попадать в браузер;
  • предоставляет расширенные права;
  • используется для административных операций;
  • может иметь доступ к управлению ресурсами.

Ограничение прав токена

С точки зрения контроля расходов крайне важно ограничивать возможности токенов.

Например:

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

Такой подход уменьшает риск несанкционированного потребления ресурсов.

Схема ограничения доменов:

example.com
app.example.com
admin.example.com

Если токен украден, злоумышленник не сможет использовать его с посторонних сайтов.


Мониторинг использования

Mapbox предоставляет панель мониторинга использования ресурсов.

Отслеживаются:

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

Анализ этих данных позволяет своевременно обнаруживать:

  • резкий рост нагрузки;
  • ошибки в коде;
  • циклические запросы;
  • несанкционированное использование токенов.

Контроль загрузок карт

Одной из наиболее частых причин неожиданного роста расходов становится повторное создание карты.

Нежелательный вариант:

button.addEventListener('click', () => {
    new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v12'
    });
});

Каждое нажатие создаёт новый экземпляр.

Более корректный подход:

let map;

button.addEventListener('click', () => {
    if (!map) {
        map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/streets-v12'
        });
    }
});

Карта создаётся только один раз.


Уничтожение карты

При работе с одностраничными приложениями рекомендуется корректно удалять ненужные экземпляры.

map.remove();

Метод освобождает:

  • обработчики событий;
  • WebGL-контекст;
  • внутренние ресурсы;
  • сетевые подписки.

Хотя удаление карты само по себе не уменьшает уже зафиксированные загрузки, оно предотвращает накопление лишних экземпляров и утечки памяти.


Использование в SPA-приложениях

Во фреймворках React, Vue и Angular карта может многократно пересоздаваться при смене компонентов.

Проблемный пример:

useEffect(() => {
    const map = new mapboxgl.Map({
        container: mapRef.current,
        style: 'mapbox://styles/mapbox/streets-v12'
    });
}, []);

Если компонент регулярно размонтируется и создаётся заново, число загрузок возрастает.

Более безопасный вариант:

useEffect(() => {
    const map = new mapboxgl.Map({
        container: mapRef.current,
        style: 'mapbox://styles/mapbox/streets-v12'
    });

    return () => map.remove();
}, []);

Такой подход обеспечивает корректный жизненный цикл карты.


Биллинг геокодирования

Сервис геокодирования оплачивается отдельно от загрузок карт.

Прямое геокодирование:

fetch(
    `https://api.mapbox.com/geocoding/v5/mapbox.places/Moscow.json?access_token=${token}`
);

Обратное геокодирование:

fetch(
    `https://api.mapbox.com/geocoding/v5/mapbox.places/37.6176,55.7558.json?access_token=${token}`
);

Каждый запрос к сервису учитывается системой тарификации.

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


Оптимизация расходов на геокодирование

Распространённый способ снижения затрат — кэширование результатов.

Пример локального кэша:

const cache = new Map();

async function geocode(query) {
    if (cache.has(query)) {
        return cache.get(query);
    }

    const response = await fetch(url);
    const result = await response.json();

    cache.set(query, result);

    return result;
}

Преимущества:

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

Биллинг маршрутизации

Сервис построения маршрутов также оплачивается отдельно.

Пример запроса:

const url =
`https://api.mapbox.com/directions/v5/mapbox/driving/
37.6176,55.7558;30.3141,59.9386
?access_token=${token}`;

Учитываются:

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

Чем активнее используется навигационный функционал, тем важнее контролировать количество запросов.


Static Images API

Для генерации статических карт используется отдельный сервис.

Пример URL:

const imageUrl =
`https://api.mapbox.com/styles/v1/mapbox/streets-v12/static/
37.6176,55.7558,10/800x600
?access_token=${token}`;

Подобные изображения часто применяются:

  • в письмах;
  • в отчётах;
  • в PDF-документах;
  • на страницах предварительного просмотра.

Запросы к Static Images API учитываются отдельно от Map Load.


Работа с собственными стилями

Пользовательские стили создаются в редакторе Mapbox Studio.

Пример подключения:

style: 'mapbox://styles/company/cl123456789'

Использование кастомного стиля не отменяет правила биллинга.

При загрузке такого стиля дополнительно запрашиваются:

  • описание стиля;
  • наборы спрайтов;
  • шрифты;
  • источники данных.

Поэтому сложные стили могут приводить к большему объёму сетевого трафика.


Оптимизация количества запросов

Уменьшение числа источников

Неэффективно:

map.addSource('roads', {...});
map.addSource('buildings', {...});
map.addSource('parks', {...});
map.addSource('water', {...});

Лучше объединять данные там, где это возможно.

Преимущества:

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

Использование векторных тайлов

Векторные данные обычно эффективнее растровых.

map.addSource('cities', {
    type: 'vector',
    url: 'mapbox://examples.cities'
});

Преимущества:

  • меньший размер передачи;
  • масштабирование без потери качества;
  • снижение нагрузки на сеть.

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

Для крупных проектов рекомендуется использовать отдельные токены:

Web Application
Mobile Application
Admin Panel
Analytics Dashboard

Такой подход позволяет понять:

  • какое приложение потребляет больше ресурсов;
  • где возникают пики нагрузки;
  • какой сервис создаёт дополнительные расходы.

Предотвращение случайных расходов

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

Структура может выглядеть следующим образом:

Development
Testing
Staging
Production

Для каждого окружения используются собственные токены.

Например:

const token =
    process.env.NODE_ENV === 'production'
        ? PROD_TOKEN
        : DEV_TOKEN;

Это помогает отделить тестовый трафик от реальных пользователей.


Работа с лимитами

Во многих проектах вводятся внутренние ограничения на использование сервисов.

Пример ограничения количества запросов:

let requests = 0;

function canMakeRequest() {
    return requests < 1000;
}

Подобный механизм может использоваться для:

  • тестовых сред;
  • бесплатных тарифов пользователей;
  • внутренних корпоративных приложений.

Аудит использования API

Регулярный аудит позволяет выявлять проблемы, влияющие на стоимость эксплуатации.

Наиболее распространённые причины перерасхода:

  1. Повторное создание карт.
  2. Зацикленные запросы геокодирования.
  3. Отсутствие кэширования.
  4. Утечка токенов.
  5. Неконтролируемая работа сторонних скриптов.
  6. Ошибки интеграции в SPA.
  7. Избыточное количество карт на одной странице.

Периодический анализ метрик позволяет поддерживать предсказуемые расходы и эффективно использовать возможности Mapbox GL JS в крупных веб-приложениях.