Как это работает: архитектура тайлового бэкенда карт «Спутника»

    Мы, команда карт «Спутника», разрабатываем карты на основе данных «OpenStreetMap». В этой заметке мы расскажем об архитектуре нашего решения для рендеринга тайлов.



    Бэкенд карт написан на языке Go с использованием библиотеки Mapnik, поэтому мы дали ему название Gopnik. Исходники Gopnik доступны на Github.

    Архитектура сервиса openstreetmap.org содержит множество компонентов.

    Пренебрегая деталями, можно выделить три основных части: базу данных PostgreSQL, API для загрузки и редактирования данных и система рендеринга карт.



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

    Коснемся некоторых общих вопросов создания on-line карт. На текущий момент существует несколько технологий отображения: от варианта, когда сервер отдает клиенту готовую картинку, до варианта визуализации загруженных данных на стороне клиента. Наибольшей популярностью на данный момент пользуются тайловые карты. Тайл — небольшое квадратное изображение с участком карты. Клиент загружает тайлы с сервера и затем склеивает их в единое изображение.

    Эта технология проста в реализации, минимально загружает клиентскую сторону. Конечно, не лишена она и недостатков, но как мне кажется, использование такой технологии будет оправдано на протяжении еще долгого времени.

    В мире OpenStreetMap стек тайловых карт держится на трех китах:

    базе данных (чаще всего PostgreSQL);
    библиотеке рендеринга (обычно Mapnik);
    клиентская javascript-библиотека (в большинстве случаев — Leaflet).

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

    Разрабатывая свой стиль мы хотели добиться одновременно полноты данных и легкости восприятия. Платой за красоту стала техническая сложность. Стиль оказался примерно вдвое более сложным и тяжеловесным, нежели стиль openstreetmap.org.

    Как следствие, обновление тайлов занимает продолжительное время (около 5 дней), необходимо кэшировать значительное количество данных (примерно 2Тб). Все это сильно осложняет жизнь.

    Чаще всего стек рендеринга строится на основе HTTP-сервера Apache c плагином mod_tile и бекендом, непосредственно занимающимся генерацией тайлов: Tirex или Renderd.



    Эта схема проверена временем, именно так и работала первая версия maps.sputinik.ru. Однако нельзя сказать, что она нас полностью устраивала. Первое, с чем мы столкнулись — проблематичность использования облачных хранилищ для тайлового кэша. mod_tile разрабатывался с оглядкой на файловую систему, а сторадж с eventual consistency использовать и вовсе невозможно без серьезной доработки. Кроме того, схема балансировки renderd имеет определенные недочеты, использовать ее в среде нескольких дата-центров затруднительно. Да и штатные утилиты особым удобством не отличаются.

    Мы провели эксперимент: набросали прототип системы, которая делает ровно то, что мы от нее хотели. Прототип прижился и получил дальнейшее развитие. По своей сути система, во многом, повторяет архитектуру mod_tile, с некоторыми расширениями и дополнениями. Она написана на языке Go с использованием библиотеки Mapnik, за что и получила свое название — Gopnik.

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

    Gopnik состоит из двух компонент: dispatcher и render. Dispatcher принимает запросы от пользователя, проверяет наличие тайлов в кэше, в случае необходимости выбирает подходящий узел в кластере по хэш-функции координат и ставит ему задачу на генерацию тайлов. Render обеспечивает непосредственно рендеринг.



    Отдельное внимание уделено проблеме взаимодействия с хранилищем. Загвоздка в том, что пользователи запрашивают тайлы по одному. Сервер же, для экономии ресурсов и для уменьшения проблем со стыковкой отдельных картинок генерирует сразу большую область карты (обычно 8x8 тайлов + дополнительный буфер), которая затем нарезается на куски. Такую область называют метатайлом. Gopnik группирует запросы от пользователя по метатайлам, при первом запросе к несохраненному в кэше метатайлу, начинается рендеринг. Все запросы, поступившие позднее, присоединяются к ожиданию. По завершении рендеринга возвращаются тайлы для всех ожидающих запросов и начинается фоновое сохранения в кэш. Кроме того, некоторое (настраиваемое) время результаты рендеринга хранятся в локальном кэше узла на случай, если клиент запросит другие тайлы из только что сгенерированного метатайла, так же локальный кэш может держать данные до полного сохранения их в сторадж, если последний поддерживает подтверждение сохранения.



    Однако на лету можно генерировать лишь те части карты, где количество данных ограничено. В остальных случаях приходится подготавливать тайлы заранее. Для этого в Gopnik'е существует специальный набор утилит.

    При помощи утилиты importer подготавливается план генерации. Prerender координирует процесс. Кластер узлов prerender slave непосредственно выполняет рендеринг.



    Система является распределенной, устойчивой к сетевым сбоям и отказу slave-узлов. Единой точкой отказа является координатор, однако, благодаря логам рендеринга, процесс может быть продолжен с места сбоя. Такое решение позволяет избежать сложных полностью распределенных систем, при этом обеспечить должный уровень отказоустойчивости.

    Исходники на Github
    Документация
    По мотивам доклада Максима Дементьева на Highload++ 2014
    Ростелеком
    Территория возможностей

    Comments 70

      +39
      Интересно, что у этой статьи на Хабре за день наверняка будет больше просмотров, чем посетителей у Спутника за тот же период времени.
        0
          0
          Мне тоже стало интересно выдержат ли эти карты Хабраэфект:)
            +1
            Не выдержали
            image
              0
              У меня тоже так висело, а через минуту где-то догрузило и потом уже без таких тормозов работало.
          +17
          Еще бы кто-нбудь объяснил вообще этот дикий велосипед под названием «Спутник» нужен…
            0
            Возможно потому, что скоро самым страшным оружием будет не ядерное, а информационное.
            –12
            Зачем, зачем. Вот начинается война, США перерубает интернет и дает команду на перманентное отключение всем Windows, а мы активируем нашу чебурашку вместо глобального интернета, включаем яндекс вместо гугла, спутник вместо гуглмэпс. Никто не заметит подмены.
              +5
              Но… у Яндекса ведь тоже есть карты…
                +2
                Но Яндекс — не совсем российская компания
                –2
                Во минусуют-то) А ведь до США может и долететь что нибудь, что не станет ни гугла, ни майкрософта. Резервные российские подобия разных заморских сервисов должны быть обязательно.
                  +1
                  То есть вместо того чтобы вести себя подобающе — мы на жопу лист металла нашьем чтобы ремнем не больно было? Хорошая тактика.
                  +2
                  Больше карт хороших и разных!
                  +15
                  «Спутник» еще существует? О_о
                    –2
                    Почему нет?
                    Обычный пользователь про него не забывает.
                      +3
                      А как на этого пользователя посмотреть? Просто интересно, какая аудитория им пользуется и где. У меня, как и у многих на хабре, наверное, нет знакомых, кто пользуется «спутником». По крайней мере я пока таких не встречал, зато встречал пару людей, которые пользуются стикерами в viber — вот это находка, но это оффтоп.
                        0
                        Теща к примеру добавила в закладки и регулярно вижу сайт на экране =)
                    +11
                    У меня вопрос о праве использования.

                    В настоящее время Соглашение об использовании гласит:

                    Материалы, входящие в состав контента, предназначены исключительно для некоммерческого использования.

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

                    А какие ещё формы использования можно считать коммерческими и поэтому не разрешёнными?

                    Не очень понятно.

                    Возможно, было бы полезно вам объяснить это обстоятельство на одном или нескольких примерах такого рода:

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

                    Какие из этих действий разрешены вашим Соглашением, а какие нет?
                      +5
                      Чтение вон той статьи в NiemanLab убеждает меня, что термин «некоммерческое использование» считается вовсе не ясным и на Западе, а не только у нас в России.

                      И поэтому он нуждается в непременном подробном разъяснении, а меж тем у «Спутника» в его Соглашении об использовании никакого разъяснения нет.
                      +1
                      Дежавю. Был ведь уже этот пост: sohabr.net/habr/post/252359/
                        –1
                        Пишите! Очень интересно как мыслит и что делает команда Спутника.
                          0
                          Вроде как ребята там на самом деле нормальные
                            0
                            Интересно какую файловую систему выбрала команда Спутника для тайлового хранилища. У меня Empty Tile занимает 103 байта. На блочной файловой системе с большим блоком это расточительно…
                            Подскажите, а какую файловую систему вы выбрали для хранения тайлов?
                              0
                                0
                                Я не очень знаком с Couchbase, но разве там отсутствуют проблемы фрагментации/незаполнения блоков?
                                  0
                                  Отсутствует. Плюс используется система дедупликации.
                                0
                                А были ли эксперименты с RamFS/TmpFS? Овчинка выделки стоит?
                                  0
                                  Как ты себе представляешь ramfs на несколько терабайт? Ок, возможно, если распределить тайлы по нескольким серверам, использую при этом хэш алгоритм. Но если сервер ребутается? Ждать n-ое количество времени пока тайлы из постоянного хранилища запишутся в ramfs?
                                    0
                                    На случай ребута лучше иметь парочку таких серверов и настроенный балансировщик, которому на время ребута одного из серверов необходимо указать использовать только оставшуюся рабочую машину.
                                    По поводу терабайт. Я рассматриваю вариант размещения в RamFS тайлов до 17-го масштаба (по моим подсчетам около 1,3ТБ). Да, это много, но нынче оперативка относительно дешевая (главное, чтобы проект этого стоил :) ).
                                    Есть еще несколько мыслей по поводу оптимизации размера tile storage. Если размещать данные, например, в Redis'е (т.е. тоже в оперативке), а не в файловой системе (даже в TmpFS), то удается сэкономить около 30% емкости за счет отсутствия необходимости хранить каталоги (которые в файловой системе, как известно, тоже занимают определенный размер), отсутствия проблем с незаполнением блоков, т.е. за счет более эффективного использования ресурса (оперативки по сравнению с файловой системой). Кстати, Redis умеет реплицироваться, что существенно упрощает решение проблемы разворачивания/ребута еще одного сервера, участвующего в балансировке.
                                    Еще я заметил, что до 70% тайлов дублируются (проверял по контрольной сумме SHA1). Как правило, это океаны, пустыни и пр. Т.е. так называемые Empty Tiles по 103 байта. Даже на этом можно попытаться сэкономить место. Например, symlink в среднем занимает 20 байт, т.е. до 70% тайлов можно в пять раз компактнее хранить, что примерно составляет около 50% емкости tile storage. Другое дело, что вычислять контрольную сумму — дело дорогостоящее для миллиардов тайлов. Пока это только мои исследования. Возможно, позже напишу статью на Хабре о результатах.
                                    P.S. Все время не покидает ощущение, что я хожу хоженными тропками, горожу велосипед и т.п., но, к сожалению, мудрость черпать неоткуда, кроме как из ваших скудных (да простите меня за откровенность) ответов.
                                      0
                                      В Couchbase тоже есть репликация, которая появилась задолго до появления оной в Redis. И тоже есть возможность хранить данные только в памяти. На тему метаданных. В Couchbase метаданные на каждое значение составляют 56 байт. Чтобы использовать метаданные с пользой, лучше в каждый ключ записывать информацию о 8x8=64 тайлах (метатайл).
                              0
                              Издёвки издёвками, а работает этот сервис реально быстро! Я зашел, потыкался, и был очень приятно удивлён.
                              Ощутимо более отзывчив, чем гугл и яндекс
                                +12
                                Не мудрено, отзывчивость обратна пропорциональна количеству пользователей.
                                  +2
                                  Советую попробовать openstreetmap.ru/, тоже довольно быстро.
                                    +1
                                    Да, но цвета там вырвиглазные.
                                      +4
                                      Там справа в меню можно разные другие стили попробовать (в том числе есть и Спутник).
                                        +2
                                        Но тогда и тайлы будут Спутника :)
                                        0
                                        Там есть красивые, похожие на Google MapSurfer с 3D, и приятные Kosmosnimki.
                                  • UFO just landed and posted this here
                                      0
                                      Там справа внизу ссылка «Обратная связь»
                                      • UFO just landed and posted this here
                                        0
                                        2) Похоже на «место для автостопщиков» и «лавочку»
                                        • UFO just landed and posted this here
                                          0
                                          Так возьми и исправь карты сам на osm.org, в чём проблема то? Это ведь открытые карты.
                                          • UFO just landed and posted this here
                                              0
                                              Значит скоро изменения доедут и до Спутника. OSM то обновляется почти вживую, а тут это итерационный процесс, судя по всему.
                                                0
                                                Где-то раз в два месяца у них обновки выкатываются.
                                                0
                                                Спутник, а как вы обрабатываете oneway=-1
                                                Есть подозрение что у вас бага.
                                                  0
                                                  Known bug.
                                                  Скоро будет в production.
                                                    0
                                                    Я бы даже сказал well known к сожалению.
                                                      0
                                                      В ближайших релизах будет поправлено. Уже исправлено, скоро на всех телевизорах страны.
                                            +1
                                            1)Сколько времени занимает обновление контента с момента правки в OSM? Последний раз прождали более 4 месяцев
                                            2)Хотим использовать карты на проекте, у нас API Openlayers. Добавление спутника в источники приводит к ошибке
                                            Image from origin 'http://c.tiles.maps.sputnik.ru' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
                                            , приходится использовать проксирование — скачивать для каждого клиента карту и передавать ему.
                                            Возможно ли добавление Access-Control-Allow-Origin:* в ответ вашего сервера?
                                              0
                                              Админы уже работают.
                                                0
                                                Вроде должно работать.
                                                +1
                                                Ого, уже первый pull request: github.com/sputnik-maps/gopnik/pull/1
                                                  +3
                                                  Радует название переменной в PR: Δt. Круто.
                                                  0
                                                  Расскажите лучше о поисковом движке. Он же на ерланге, да?
                                                    0
                                                    Если вы про геопоиск, то он тоже на Go.
                                                      0
                                                      Нет, про обычный. Я вот эту вакансию на hh.ru видел и приметил что в юзаете erlang
                                                    0
                                                    A сколько уровней tiles?
                                                      0
                                                      18, идем на 19 :)
                                                      0
                                                      А на сервисе спутника только векторные карты? Спутниковых снимков не предусмотрено?
                                                        0
                                                        А каким импортером osm вы пользуетесь?
                                                        У нас импорт RU.osm.pbf на osm2pgsql занимает 691 минуты, а на imposm3 11 минут.
                                                        Если вы пользуетесь imposm3, то меняли ли вы маппинг в imposm3 или в mapnik?
                                                          0
                                                          Это для планеты? А можно узнать конфигурацию машины?
                                                            0
                                                            Это для RU.osm.pbf
                                                            1x E5-2650v2 / 128GB RAM / 2x 800GB SSD Intel s3500 / dm raid1 / lvm / ext4 (blk sched deadline)
                                                            CentOS 7.1 x86_64 / posgtresql 9.4 полностью в ramfs
                                                              0
                                                              Ой, сори, не заметил сразу что только RU, но в любом случае железо приличное (это все объясняет), еще +столько же оперативки и можно собирать всю планету в RAM :)
                                                            0
                                                            Какой в итоге маппинг Вы используете для данных, импортированных через imposm3?

                                                          Only users with full accounts can post comments. Log in, please.