OpenStreetMap — тайловый сервер

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

И вот мне понадобилось его добавить в свой рабочий проект. Для этого есть 2 пути: использовать официальный сервис либо поднять свой сервер. Второй вариант может быть использован по ряду своих причин и какие были причины у меня останутся при мне.

Пример сгенерированного тайла

Подготовка

Для начала нужно определиться на чем это все разворачивать. В моем распоряжении есть сервер с мелкомягкими на 192ГБ ОЗУ и 8 ядрами процессора (16 потоков). Теперь подумаем как это все расположить.

Так как это сервер уже с какими-то ГИСами, то плодить еще кучу виртуалок не хочется. Попробуем все это уместить в более скромный набор «всего» и «вся».

На сервер уже есть PostgreSQL 14, хоть и не настроенный, а просто установленный (он нужен и для других ГИС-систем).

Судя по просмотру материала тайловый сервер все равно придется делать на Linux. Тогда понадобится виртуальная машина. Тут снова 2 вариант: создать виртуалку на сервере виртуализации (у нас в основной массе используется ProxMox) либо создать виртуалку на Hyper-V. Второй вариант тоже предпочтительней, так как весь абор будет находиться на одной железке. Создаем виртуалку и выделяем ей 8ГБ ОЗУ и 4 ядра ЦПУ. В качестве ОС накатываем Линух (у меня Debian 11). После установки не забываем настроить адреса и SSH.

Вальс в троем

Первым делом нужно установить PostGIS (без него вообще никак) на Windows-сервер. Это специально расширение для PostgreSQL. Загружаем, устанавливаем. После открываем pgAdmin4 (он должен входить в стандартную поставку с PostgreSQL for Windows) и создаем пользователя для БД (в моем случае «osm», задаем пароль и выставляем для него права «Can login». Далее создаем БД для работы (в моем случае опять же «osm») и в качестве владельца указываем ранее созданного пользователя. После для БД выполняем запросы со страницы https://postgis.net/install/, чтобы расширение PostGIS установилось для базы и еще одну команду:


CREATE EXTENSION hstore;

Расширение hstore нужно для хранения тэгов карты.

Сюда же нужно загрузить утилиту osm2pgsql.

Теперь переходим на виртуалку иустанавливаем целый ворох программ:


apt install mapnik lipapache2-mod-tile python-psycopg2 python2-yaml python3-yaml git npm nodejs fonts-noto-hinted fonts-noto-unhinted ttf-unifont fonts-noto-cjk fonts-hanazono libmapnik-dev mapnik-utils python3-mapnik

Далее понадобится пакет для генерации стиля тайлов карты:


npm -g i carto

После загружаем непосредственно стили:


git clone https://github.com/gravitystorm/openstreetmap-carto.git
cd openstreetmap-carto

Теперь открываем на редактирование файл project.mm, изменяем параметры подключения к БД в разделе osm2pgsql. В частности такие параметры как «dbname«,» host», «user» и «password». После выполняем команду:


carto project.mm > mapnik.xml

После подготовки необходимо скопировать файлы openstreet-carto.lua и openstreet-carto.style на Windows-сервер и положить их рядом с osm2pgsql.

Далее идем на сайт download.geofabrik.de, выбираем нужную карту и загружаем «.osm.pbf».

Пока выполняется загрузка карты можно сделать настройку PostgreSQL (если до этого еще не было настроено). Для этого берем PGTune (ищем в интернете), указываем необходимые параметры, вбиваем в утилиту и получаем параметры настрокий. Загоняем их в postgresql.conf. Эту операцию нужно делать только в случае ПЕРВОНАЧАЛЬНОЙ УСТАНОВКИ PostgreSQL. Вообще, по хорошему, есть специальные рекомендации настрокий. Все это прекрасно гуглится и яндексится.

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


osm2pgsql.exe -c -m -G --slim --hstore --tag-transform-script c:\maps\openstreet-carto.lua -d <имя БД> -H localhost -U <логин> -W -S c:\maps\openstreet-carto.style c:\maps\russia-latest.osm.pbf

Карта может импортироваться достаточно долго (в зависимости какая была выбрана). Возвращаемся на виртуалку и продолжаем настройку.

Здесь открываем /etc/renderd.conf и приводим примерно к следующему виду:


[renderd]
stats_file=/run/renderd/renderd.stats
socketname=/run/renderd/renderd.sock
num_threads=4
tile_dir=/var/cache/renderd/tiles
;tile_dir=/var/lib/mod_tile

[mapnik]
plugins_dir=/usr/lib/mapnik/3.1/input
font_dir=/usr/share/fonts/truetype
font_dir_recurse=true

[default]
XML=/root/openstreetmap-carto/mapnik.xml
URI=/tile/
TILESIZE=256
HOST=localhost
TILEDIR=/var/lib/mod_tile

По факту добавляем/правим раздел [default]. Так же при необходимости нужно поправить параметр num_threads. Директории /var/lib/mod_tile нету, по этому нужно создать и выдать соответствующие права доступа:


mkdir /var/lib/mod_tile
chown -R _renderd:_renderd

После в файле /etc/apache2/ports.conf правим порт с 80 на 8080 (ну или требуемый по вкусу). В заключении в /etc/apache2/sites-available создаем файл tileserver_site.conf:



    ServerAdmin         admin@osm.net

    #ServerName         osm.net
    DocumentRoot        /var/www/osm

    LogLevel info

    ModTileTileDir /var/lib/mod_tile
    LoadTileConfigFile /etc/renderd.conf
    ModTileRequestTimeout 30
    ModTileMissingRequestTimeout 60
    ModTileMaxLoadOld 2
    ModTileMaxLoadMissing 25
    ModTileRenderdSocketName /var/run/renderd/renderd.sock
    ModTileCacheDurationMax 604800
    ModTileCacheDurationDirty 900
    ModTileCacheDurationMinimum 10800
    ModTileCacheDurationMediumZoom 13 86400
    ModTileCacheDurationLowZoom 9 518400
    ModTileCacheLastModifiedFactor 0.20
    ModTileEnableTileThrottling Off
    ModTileEnableTileThrottlingXForward 0
    ModTileThrottlingTiles 10000 1 
    ModTileThrottlingRenders 128 0.2

    
        Options FollowSymLinks
        AllowOverride None
    
    
        Options -Indexes -FollowSymLinks -MultiViews
        AllowOverride None
        Order Allow,Deny
        Allow From All
    


Включаем конфиг:


/usr/sbin/a2ensite tileserver_site
systemctl restart apache2

После окончания импорта карты на том же web-сервере нужно выполнить некоторые скрипты. Для этого возвращаемся в директорию openstreetmap-carto и запускаем скрипт:


scripts/get-external-data.py -d <имя БД> -U <логин> -w <пароль> -H <адрес сервера БД>

Добавляем карты

Допустим, загрузили мы только один регион. Но а если хочется добавить еще один? Не проблема! Все тот же osm2pgsql с этим прекрасно справляется. Озадачиваем его следующим образом:


osm2pgsql.exe -a -m -G --slim --hstore --tag-transform-script c:\maps\openstreet-carto.lua -d <имя БД> -H localhost -U <логин> -W -S c:\maps\openstreet-carto.style f:\belarus-latest.osm.pbf

Ну и , собственно, ждем пока загрузится новый файл.

Хочу видеть результат

В общем то все готово, но хочется все это увидеть.

Для начала остановим renderd и запустим его в интеррактивном режиме (для отладки):


systemctl stop renderd
renderd -f -c /etc/renderd.conf

После можно открыть в браузере http://<ваш адрес>:8080/tile/0/0/0.png. В результате должен открыться тайл карты. Если нет, то смотрим консоль и логи web-сервера.

Но ведь хочется больше интеррактивности…

По пути /var/www/osm добавляем файл index.html со следующим содержимым:


<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/css/ol.css" type="text/css">
    <style>
      .map {
        height: 400px;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.14.1/build/ol.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <h2>My Map</h2>
    <div id="map" class="map"></div>
    <script type="text/javascript">
      var map = new ol.Map({
        target: 'map',
        layers: [
          new ol.layer.Tile({
            source: new ol.source.XYZ({url: 'http://<ваш сервер>:8080/tile/{z}/{x}/{y}.png'})
          })
        ],
        view: new ol.View({
          center: ol.proj.fromLonLat([37.41, 8.82]),
          zoom: 4
        })
      });
    </script>
  </body>
</html>

И открываем http://<Ваш сервер>:8080. Должна появиться карта. Если нет, то проверяем ошибки.

Подводный камень

В моем случае была крайне низкая скорость. Причина этому были настройки сети в Hyper-V. Не известно по каким причинам, но виртуальный сетевой адаптер работал через мост и СУБД крайне медленно передавала данные. Коллега подсказал, что нужно избавиться от моста, после чего сеть начала работать так как нужно.

Немного оптимизации

В статье OSM User:Species/PostGIS Tuning описаны дополнительные индексы, которые могут помочь оптимизировать производительность базы. Здесь я их приводить не буду, так как в ней все очень хорошо расписано и в комментариях не нуждается.

Поделиться
Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий

Вы должны быть авторизованы, чтобы разместить комментарий.