… эта история началась давным-давно в далекой-далекой стране Краковия, чьи жители беспечно проживали свои жизни и не знали…

Но сам я местный, и сегодня расскажу вам страшную историю, о том, что мешало спать (лично мне) долгие годы. И это не налоги (с ними все нормально), это — геокодер Яндекс.Карт!
Геокодер — это один из HTTP-сервисов Яндекс.Карт, получающий в запросе текстовое представление адреса и возвращающий в ответе найденные на его основании объекты. Либо наоборот: получающий координаты и отвечающий адресом.

Именно геокодер подскажет, где на карте находится чудная страна Краковия. И именно он будет главным героем этой истории, завязка которой была описана совершенно в другой книге — в древнем фолианте Пользовательское соглашение API Яндекс.Карт. Легенда гласит, что существует ограничение на количество запросов к функции геокодирования. Максимально допустимо делать в сутки не более 25 000 запросов к HTTP и JS геокодеру в сутки. Или овсянка, сэр.

И буквально на днях это правило из обычных слов превратилось в угрозу работоспособности сайта. В клубе API Карт было опубликовано сообщение о массовых банах различных сервисов, превышающих лимиты.



Что делать? Для наглядности достанем из кустов рояль — 8 лет назад на Хабре засветился проект «еСоседи» — «Карта интересных мест». Все эти годы я продолжаю работать над ним.

У части мест, которые рисовали пользователи на карте, были только координаты на карте — для них надо было узнать адрес. У других мест, найденных в различных источниках, был наоборот известен только адрес. А значит, его надо было перевести в координаты для отображения на карте.

Более того — перевод координат в адрес и обратно надо было повторять регулярно!
По правилам использования сервиса ответ геокодера нельзя сохранять в базу навсегда, но можно кешировать до 30 дней. Дело не в том, что Яндекс не хочет делиться данными, просто качество данных и покрытия постоянно меняется, а мне, как создателю сервиса, было важно, чтобы самая свежая информация была доступна пользователю. Краковию, кстати, до сих пор не находит.

Кроме этого на сайте «еСоседи» ежедневно бывали десятки тысяч человек, которые искали какие-нибудь места, что снова приводило к использованию геокодера.

На самом деле, всё могло бы быть не так страшно, если бы не лень и вера в ЧУДО! Смотрите:

ymaps.geocode('Тимура фрунзе д.12').then(function(res){myMap.geoObjects.add(res.geoObjects);});
//или даже
ymaps.geoQuery(ymaps.geocode('Арбат')).addToMap(myMap);

В результате простой операции на карте появится одна или более точек и именно в нужном месте. Ну разве не чудо?

Ослепленные простотой использования JS-геокодера многие разработчики именно так программировали свои «картографические решения». Отобразить банкоматы, отделения почты, свои точки продаж или любые другие «организации», привязанные к адресу, реально проще, если работать только с адресами.

Тексты будут проглочены АПИ, где-то там в глубинах магически переварятся — и на карте появятся метки в нужных местах. Я вам даже больше скажу — многие люди не видят разницы между заданием месторасположения какой либо метки числовыми координатами или юридическим адресом.

Беда в том, что за все волшебство надо платить! А еще надо ходить в ручку и вставать на счетчик. И если у вас есть одна страничка, на ней 10 меточек, и 2 500 человек в день — значит вы уперлись в лимит.
Раньше при пересечении границы в 25 000 запросов в сутки, могло прийти письмо от менеджера из Яндекса с объяснением, что вы делаете не так. Теперь придёт злой робот с плюсометом — и все.

Именно это мешало мне спать последние дни. Одна из частей «еСоседей» — это материализация КЛАДР (города, улицы, адреса) — postindex.esosedi.ru. Это база данных «про адреса» и, конечно же, она описывается адресами (текстом) и часто не содержит координат. Даже сейчас многие поселки нашей большой Родины не геокодируются (помни про Краковию). Так что координаты — это вторично.

При каждом заходе на страницу города или улицы показывается карта. При этом отправляется запрос по переводу известного адреса (Тимура Фрунзе, 11к2) в координаты. Кстати, геокодирование происходит не мгновенно, и, если точек у вас много, может замедлить загрузку карты.

Все бы ничего, да 40 000 отделений почты, 211 000 населенных пунктов, миллион улиц, 55 000 посетителей за вчера… Этого хватит на два суточных лимита с хвостиком. Но многие годы это именно так и работало. А все почему?



Не будем ждать злого робота — будем решать проблему. К счастью решение существует, и не одно, а два.

Решение первое — правильное


Модифицировать backend так, чтобы было куда сохранять координаты. А это значит, сделать нормальную админку, посадить девушку, которая на основе визуального осмотра «ответа» геокодера будет выставлять TTL данным, двигать иконки, достигая сантиметровой точности размещения меток…

Плюсы: технологично, надежно, красивая девушка в офисе.
Минусы: требуется бэкенд, требуется БД, не совсем понятно что делать с пользовательским поиском; не совсем понято, как отреагирует жена.

Решение второе — дешевое и сердитое


Сделать свой поиск! Такой, чтобы что-то в себя сохранял (т.е. кэширующий прокси), был «из коробки», чтобы справлялся с одновременными одинаковыми запросами и так далее.

В общем идея очень проста: ходить в некую собственную ручку, там проверять состояние кэша и, если нужных данных нет, отправлять запрос в HTTP-геокодер Яндекс.Карт.

Для многих крупных проектов правильным решением будет написать что-то свое. Быть может даже развернуть совсем свой геокодер, например, на основе OSM.

Но по опыту знаю, что для большинства самый выгодный вариант — взять что-то готовое с github. По традиции даю ссылку на geocode-tool вариант решения проблемы от dimik. Дима когда-то работал Яндекс.Картах и никак не может остановиться.

В общем случае geocode-tool это серверная часть («ручка»), web-интерфейс со статистикой, и модуль для Яндекс.Карт.

Минусы: требуется запускать на сервере еще один сервис, к тому же на ноде. В офисе не появится девушка.
Плюсы: Вся работа свелась к скачке репы и добавлению пары строчек на клиенте (ну почти).

Если у вас на сайте есть карта хотя бы со схемой проезда, и используется геокодирование (проверьте), а также вам кажется, что оно выполняется часто, подключите себе проксирующий сервер. Если у вас на каждой странице происходит трансформация адреса, используйте серверный геокодер или устанавливайте координаты напрямую.

1000 человек, которые посетят 10 страниц абстрактного магазина, где на каждой странице есть схема проезда, по 2 точки (адреса) на каждой — это уже 20 000 запросов, что опасно близко к лимиту. Вдруг однажды вы решите купить рекламу, и сайт посетит немного больше людей?

Чем кончилось это у нас, на «еСоседи»:
  • Подключение локального кеша позволило ускорить страницу в среднем на 150мс — доступ к геокодеру в условиях массовой загрузки картинок и другой рекламы дело не быстрое.
    При генерации кода страницы в начале дергается кеш геокодера, минуя оригинальный сервис, и только если там нет ответа добавляется вызов функции на клиенте. PS: серверная версия этого дела на github опять же есть.
  • Наконец появилась статистика по запросам!
  • После появления административного деления(статья на хабре) и нормального кеша геокодера стало возможно постфактум проверять правильность работы обоих.

Именно что — не забывайте что геокодер не искусственный разум — может выдавать фигню.



Как известно на юге Москвы четыре(1,2,3,4) Свитино и все примерно в одном месте, но два из них в Москве, одно — в Московской области, а еще одно — в Калужской.

Геокодер — это простой механиз поиска по базе, а значит он может выдать немного не тот обьект, который хочется. Например, потому что искомого на самом деле нет (помни о Краковии).

Это все веселее чем кажется. Но! Я! Наконец! Могу спать спокойно. Чего и вам советую.

Хорошего геокеширования.

PS: На самом деле над «еСоседи» я работаю в свободное от основной работы время. А основная работа как раз в Яндекс.Картах. И я вас предупредил.

PPS: Все картинки от fevrony.

Комментарии (9)


  1. zaleslaw
    30.07.2015 19:21
    +1

    Одно рукой лимиты ставим, другой бекенды свои переписываем?)))


    1. kashey Автор
      30.07.2015 19:26
      +3

      И фару, фару на лоб, чтоб и фронткенд…


  1. NickKolok
    30.07.2015 20:44
    +2

    Шаг следующий — децентрализация: если в «своём» кэше не найдено, быстренько попинать «соседей», у кого-то, да может оказаться.


  1. Milfgard
    30.07.2015 20:47
    +2

    >Дима когда-то работал Яндекс.Картах и никак не может остановиться.
    Вот эта фраза теперь не будет давать спать мне.


  1. Tark
    30.07.2015 22:35

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


    1. kashey Автор
      30.07.2015 22:54
      +1

      Мешает тоже самое что и Иннокентию — диван. Но вообще вы описали вариант решения №1 — вроде как нормальный, но его же «делать» надо — админка не у всех есть.


      1. Tark
        30.07.2015 22:56
        +1

        Виноват, это я пропустил. Выходит, что самое быстрое решение — почти всегда самое неправильное :)


        1. kashey Автор
          30.07.2015 23:05

          Самое быстрое решение — часто единственно возможное. Главное потом не забыть залатать пробоины.
          Для многих случаев, например обработки километров строк из exel, «свой» геокодер, свой кеш, свои автоисправлялки(типа dadata.ru) — полезности уровня must have. В том плане, что первая нормальная форма БД с координатами это одно, а «магия», которая в том числе снижает итоговую нагрузку из-за обработки «похожих» и общего кеша — другое.


  1. dimik
    31.07.2015 11:23
    +1

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