Тайловый сервер OpenStreetMap

OpenStreetMap (OSM) — это создаваемая пользователями, свободно редактируемая карта мира. Можно представить это как альтернативу Google Maps с открытым исходным кодом. Эта инструкция покажет, как создать свой собственный сервер тайлов (tiles) OpenStreetMap в Ubuntu 20.04, чтобы вам не пришлось использовать собственный картографический сервис.

Требования для развёртывания карты всей планеты довольно высоки:
Минимум 32Гб ОЗУ
1ТБ пространства на SSD

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

Для установки делаем следующие шаги.

Устанавливаем базу данных PostgreSQL

sudo apt install postgresql-12 postgresql-contrib postgis postgresql-12-postgis-3 -y

Настраиваем пользователей

sudo -u postgres createuser osm
sudo -u postgres createdb -E UTF8 -O osm gis
sudo -u postgres psql -c "CREATE EXTENSION postgis;" -d gis
sudo -u postgres psql -c "CREATE EXTENSION hstore;" -d gis
sudo -u postgres psql -c "ALTER TABLE spatial_ref_sys OWNER TO osm;" -d gis

Добавляем пользователя для работы с базой данных

sudo adduser --system --group osm

Даём необходимые права на директорию с картами текущему пользователю

cd /home/osm/
sudo apt install acl
sudo setfacl -R -m u:administrator:rwx /home/osm/

Копируем репозиторий проекта карт

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

Скачиваем файлы карт

Есть сайт https://download.bbbike.org/osm/bbbike/ откуда можно скачать отдельные карты городов

Есть файлы областей планеты — http://download.geofabrik.de/index.html

Скачивать надо файлы расширением .osm.pbf

Если требуется показывать карты нескольких стран, то необходимо скачивать карты каждой страны по отдельности и объединять их. Процедура объединения будет показана ниже

Скачаем карту России по примеру ниже

cd /home/osm/
wget -c http://download.geofabrik.de/russia-latest.osm.pbf

Пока скачиваются карты, настроим сервер PostgreSQL для работы с картами

sudo nano /etc/postgresql/12/main/postgresql.conf

Ищем и заменяем параметры, чтобы они были со значениями как указано ниже

shared_buffers = 15GB # (0.25*RAM)
work_mem = 1GB # (1/60 RAM или около гигабайта ОЗУ)
maintenance_work_mem = 8GB # (0,125*RAM)
effective_cache_size = 20GB # (1/3*RAM)

Перезагружаем сервис

sudo systemctl restart postgresql

По умолчанию PostgreSQL будет пытаться использовать HugePages в оперативной памяти. Однако Linux по умолчанию не выделяет HugePages. Получим объём памяти процесса PostgreSQL.

grep ^VmPeak /proc/$(sudo head -1 /var/lib/postgresql/12/main/postmaster.pid)/status
VmPeak: 16282784 kB

Это максимальный объем памяти, который будет использоваться PostgreSQL. Теперь проверим размер HugePage в Linux.

cat /proc/meminfo | grep -i huge

Вывод команды:

AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB

Теперь можно подсчитать, сколько нужно HugePages. Разделим значение VmPeak на размер HugePage: 16282784 кБ / 2048 кБ = 7950. Отредактируем файл /etc/sysctl.conf.

sudo nano /etc/sysctl.conf

Вставим в начало следующий параметр

vm.nr_hugepages = 7950

Применим изменения

sudo sysctl -p
sudo systemctl restart postgresql

Следующий шаг — импорт файлов карт в базу данных

Импорт карт в БД

Для импорта карт в базу данных необходима утилита osm2pgsql

sudo apt install osm2pgsql -y
sudo setfacl -R -m u:postgres:rwx /home/osm/

Для импорта нескольких карт их можно объединить программой osmconvert из комплекта утилит osmctools

sudo apt install osmctools

Объединяем скачанные карты

Используем несколько карт скачанных стран

cd /home/osm/
osmconvert <(osmconvert belarus-latest.osm.pbf --out-o5m) \
<(osmconvert finland-latest.osm.pbf --out-o5m) \
<(osmconvert georgia-latest.osm.pbf --out-o5m) \
<(osmconvert kazakhstan-latest.osm.pbf --out-o5m) \
<(osmconvert russia-latest.osm.pbf --out-o5m) \
<(osmconvert ukraine-latest.osm.pbf --out-o5m) -o=merged.pbf

Импортируем карты в базу . Процесс импорта долгий и занимает примерно 5 часов на SSD. Можно предварительно запустить процесс импорта в screen’е

sudo -u postgres -i
osm2pgsql --slim -d gis --hstore --multi-geometry --number-processes 24 \
--tag-transform-script /home/osm/openstreetmap-carto/openstreetmap-carto.lua \
--style /home/osm/openstreetmap-carto/openstreetmap-carto.style -C 32000 /home/osm/merged.pbf

, где
—slim — указывает osm2pgsql создавать “тонкие” таблицы для хранения данных при импорте, а не пытаться хранить все в памяти. —slim также необходим, если мы хотим обновить данные;
-d gis — выбор базы
—hstore — это хранилище ключей и значений, поддерживающее произвольные ключи и значения;
—multi-geometry — указывает osm2pgsql не разбивать мультиполигоны на отдельные полигоны. Это повышает гибкость и устраняет некоторые артефакты визуализации, но немного медленнее.
—number-processes — количество ядер используемых у процессора;
—style — путь к файлу стиля, который сообщает osm2pgsql, какие столбцы создавать;
-С 32000 — размер кэша в мегабайтах. Должен быть примерно 70% от свободной памяти. Учитывайте, что PostgreSQL также использует память для shared_buffers. Общая формула для вычисления кеша такова: (Всего ОЗУ — PostgreSQL shared_buffers) * 0,7

После импорта даём права osm на таблицы базы

psql -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO osm;" -d gis
exit

Устанавливаем утилиты для рендеринга карт

Это mod_tile и renderd
mod_tile-это модуль Apache, необходимый для обслуживания тайлов (или плиток), а renderd — демон рендеринга для рендеринга тайлов OpenStreetMap.

sudo apt install software-properties-common
sudo add-apt-repository ppa:osmadmins/ppa
sudo apt install libapache2-mod-tile renderd -y
sudo apt install curl unzip gdal-bin mapnik-utils libmapnik-dev python3-pip -y
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g carto
sudo -H pip3 install psycopg2==2.8.2

Версия psycopg2 именно 2.8.2, потому что при загрузке внешних границ, на новой версии возникнет ошибка вакуума.

sudo -u postgres -i
cd /home/osm/openstreetmap-carto/
scripts/get-external-data.py
carto project.mml > style.xml
psql -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO osm;" -d gis
exit

Ставим шрифты для корректного отображения не-ASCII символов

sudo apt install ttf-dejavu fonts-noto-cjk fonts-noto-cjk-extra fonts-noto-hinted fonts-noto-unhinted ttf-unifont -y

Настраиваем renderd

sudo nano /etc/renderd.conf

Содержимое:

[renderd]
stats_file=/var/run/renderd/renderd.stats
socketname=/var/run/renderd/renderd.sock
num_threads=24
tile_dir=/var/lib/mod_tile

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

[default]
URI=/osm/
XML=/home/osm/openstreetmap-carto/style.xml
DESCRIPTION=This is the standard osm mapnik style
;ATTRIBUTION=&copy;<a href=\"http://www.openstreetmap.org/\">OpenStreetMap</a> and <a href=\"http://wiki.openstreetmap.org/w\
iki/Contributors\">contributors</a>, <a href=\"http://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>
HOST=tile.example.com
;SERVER_ALIAS=http://a.tile.openstreetmap.org
;SERVER_ALIAS=http://b.tile.openstreetmap.org
;HTCPHOST=proxy.openstreetmap.org

Настроим параметры запуска renderd

sudo nano /etc/init.d/renderd

И меняем имя пользователя

RUNASUSER=osm

Применяем изменения

sudo systemctl daemon-reload
sudo systemctl restart renderd

Даём права пользователю на чтение плиток

sudo chown osm /var/lib/mod_tile/ -R

Настраиваем apache2

sudo nano /etc/apache2/sites-available/tileserver_site.conf

и указываем

ServerName tile.example.com

Перезапускаем apache2

sudo systemctl restart apache2

Настраиваем отображение карт в браузере

Используем Leaflet

cd /var/www/
sudo wget http://cdn.leafletjs.com/leaflet/v1.7.1/leaflet.zip
sudo unzip leaflet.zip

Создаём файл показа карты

sudo nano /var/www/index.html
<html>
<head>
<meta charset="UTF-8">
<title>OSM Tile</title>
<link rel="stylesheet" type="text/css" href="leaflet.css"/>
<script type="text/javascript" src="leaflet.js"></script>
<style>
   #map{width:100%;height:100%}
</style>
</head>

<body>
  <div id="map"></div>
  <script>
    var map = L.map('map').setView([60,31.0],9);
    L.tileLayer(
    'http://tile.example.com/osm/{z}/{x}/{y}.png',{maxZoom:18},
    ).addTo(map);
</script>
</body>
</html>

Карты доступны по адресу http://tile.example.com

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии