Установка OpenStreetMap Nominatim для нахождения широты и долготы по введенному адресу

image

Хотел бы поведать свою историю об установке геокодера Nominatim на выделенный сервер. Изначально предполагалось, что эта задача займёт у меня около 5-7 часов, но не тут то было… Поэтому было решено написать статью c описанием разворачивания Nominatim на сервер до полной работоспособности сайта. Но обо всём по порядку.

Введение


Есть множество сервисов с геокодерами, не буду здесь их всех перечислить, отмечу, что на Хабре есть хорошие статьи по этому поводу: «Geocoding with PHP and the Google Maps API», а также «Яндекс Карты: Поиск произвольных объектов».

Для тех кто не в курсе: Geocoding — это процесс нахождения широты и долготы по введенному адресу.
Мой выбор пал именно на Nominatim, так как его можно развернуть на своём сервере и не ограничиваться количеством запросов, а также уже был опыт работы с OSM картами и хотелось бы его применить.

Документация


Сайт с уже работающей картой можно найти по ссылке: OpenStreetMap Nominatim
А вот и ссылка на примеры запросов: Wiki nominatim
Так же есть ссылка на установку Nominatim Installation. Но эта документация немного устарела, для установки именно по этой статье необходимо немного потанцевать с бубном. Всё ниже описанное, будет ссылаться на эту статью по установке, только без участия бубна.
А так же есть докер контейнер nominatim docker. По какой-то причине, скорее всего из-за устаревших пакетов установки, этот контейнер у меня таки не запустился.

Шаг 1: Создание виртуальной машины


За основу была взята машина из облака Microsoft Azure серии standart D2 с характеристиками: 2 cores, 7 GB RAM, 100 GB SSD. Именно на этой машине и будет производиться установка Nominatim. 100GB на самом деле — это больше чем нужно для моей задачи, так как карта Украины не настолько большая. После установки всех необходимых компонентов осталось свободных 70%.

Шаг 2: Установка необходимых пакетов


sudo apt-get update
sudo apt-get -y install wget
sudo apt-get -y install build-essential automake
sudo apt-get -y install libxml2-dev
sudo apt-get -y install libgeos-dev
sudo apt-get -y install libpq-dev
sudo apt-get -y install libbz2-dev
sudo apt-get -y install libtool libproj-dev
sudo apt-get -y install libgeos++-dev
sudo apt-get -y install gcc proj-bin libgeos-c1 git osmosis
sudo apt-get -y install php5 php-pear php5-pgsql php5-json
sudo apt-get -y install bc
sudo apt-get -y install postgresql-9.4 postgresql-9.4-postgis-2.1 postgresql-contrib-9.4 postgresql-server-dev-9.4
sudo apt-get -y install libboost-chrono1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev
sudo apt-get -y install python-software-properties && add-apt-repository -y ppa:kakrueger/openstreetmap && apt-get update && apt-get --no-install-recommends install -y osm2pgsql

Шаг 3: Настройка


sudo -i
pear install DB
sudo -u username
sudo mkdir -p /app/nominatim
sudo -i
useradd -m -p password1234 -d /app/nominatim nominatim
chown nominatim: /app/nominatim
cd /app/nominatim
wget http://www.nominatim.org/release/Nominatim-2.4.0.tar.bz2
tar xvf Nominatim-2.4.0.tar.bz2
rm Nominatim-2.4.0.tar.bz2
mv Nominatim-2.4.0/* .
rm Nominatim-2.4.0/
sudo -u nominatim ./autogen.sh
./configure && make

Думаю, в этих строках команд не сложно разобраться. В случае если возникнет ошибка с получение прав доступа, установим права доступа на чтение и запуск на выполнение всем пользователям и группам chmod -R 755 /app. Хотелось бы отметить, что иногда возникала проблема при выполнении команды make. если у вас возникла эта проблема воспользуйтесь командой sudo make clean, а затем уже ./configure && make.

Шаг 4: PostgreSQL


Изначально, postgres настроен не для боевого сервера, так что надо его конфигурировать вот советы от wiki документации nominatim:
Ubuntu location /etc/postgresql/9.x/main/postgresql.conf
CentOS location /var/lib/pgsql/data/postgresql.conf

shared_buffers (4GB)
maintenance_work_mem (10GB)
work_mem (50MB)
effective_cache_size (24GB)
synchronous_commit = off
checkpoint_segments = 100
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
The numbers in brackets behind some parameters seem to work fine for 32GB RAM machine

sudo passwd postgres
sudo usermod -a -G sudo postgres
service postgresql start && pg_dropcluster --stop 9.4 main
service postgresql start && pg_createcluster --start -e UTF-8 9.4 main

service postgresql start && sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='nominatim'" | grep -q 1 || sudo -u postgres createuser -s nominatim && sudo -u postgres psql postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='www-data'" | grep -q 1 || sudo -u postgres createuser -SDR www-data && sudo -u postgres psql postgres -c "DROP DATABASE IF EXISTS nominatim"

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

Шаг 5: Загрузка и установка osm карт


В начале необходимо загрузить саму карту из сайта в формате *.pbf: OpenStreetMap Data Extracts. В качестве примера я загружаю карту Украины и переименовываю в data.pbf.

wget --output-document=data.pbf http://download.geofabrik.de/europe/ukraine-latest.osm.pbf
chown nominatim: data.pbf
touch local.php /app/nominatim/settings/local.php
nano /app/nominatim/settings/local.php

Последняя команда открывает файл конфигураций по установке nominatim. В файл local.php нужно ввести код который описан ниже.

<?php
   // Paths
   @define('CONST_Postgresql_Version', '9.4');
   @define('CONST_Postgis_Version', '2.1');
   
   // Website settings
   @define('CONST_Website_BaseURL', 'http://geocoder.cloudapp.net/');
?>

В качестве BaseURL необходимо вписать адрес сайта, с которого будет запущен nominatim.

Теперь запускаем команду установки nominatim. Эта операция занимает довольно таки длительное время, например с картой Украины установка длилась около 7 часов. В силу того, что я выполнял все команды через ssh, и являюсь подверженным переменному отключению интернета, выполнение команды установки проводится в скрине.

screen
service postgresql start && sudo -u nominatim -- ./utils/setup.php --osm-file /app/nominatim/data.pbf --all --threads 2 2>&1; sudo -u nominatim -- ./utils/setup.php --index --create-search-indices

Для выхода из скрина нужно набрать комбинации Ctrl+A затем Ctrl+D. Команда screen -r возвращает обратно в скрин.

Теперь запустим сайт быстрым способом:

./utils/setup.php --create-website /var/www/html
rm /var/www/html/index.html
/etc/init.d/apache2 restart

Я обошелся без настройки apache или работой с nginx, так как об этом вы с легкостью можете прочитать на Хабре в других статьях. Да и без настройки сайт прекрасно работает.

Тестируем сайт


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

image

Проверим как работает api, сделав запрос:
http://geocoder.cloudapp.net/?format=json&addressdetails=1&q=Odessa&format=json&limit=1
Response:

[{"place_id":"1145869","licence":"Data © OpenStreetMap contributors, ODbL 1.0. http:\/\/www.openstreetmap.org\/copyright","osm_type":"relation","osm_id":"1413934","boundingbox":["46.342707","46.6291187","30.6114013","30.8313753"],"lat":"46.4858883","lon":"30.68365101101","display_name":"Одесса, Одесская область, Украина","class":"place","type":"city","importance":0.45,"icon":"http:\/\/geocoder.cloudapp.net\/images\/mapicons\/poi_place_city.p.20.png","address":{"city":"Одесса","county":"Одесса","state":"Одесская область","country":"Украина","country_code":"ua"}}]

Выводы


В конце хотелось бы подметить, что для загрузки карты Земли нужно сервер по мощнее, чем серия D2, если вы не хотите *неделю ждать загрузки. Эту проблему так же можно решить с помощью временного масштабирования сервера до серии D14 (16 ядер, 112 ГБ памяти). А вот время выполнение запроса поиска очень радует: в среднем поиск по Украине занимает всего 300мс.

Надеюсь, данная статья поможет другим разработчикам потратить меньше времени на разворачивание Nominatim и понять, нужно ли вам это. Может стоит взять уже готовое и использовать?

Если у кого-то из хабросообщества будет необходимость в рабочем Docker контейнере с Nominatim, или другие идеи — пишите, всегда рад пообщаться.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 28

    +1
    Пользовался когда-то
    github.com/cyclestreets/nominatim-install

    С докером — их несколько, вроде есть более менее свежий.
        0
        Да, получается что они не очень и свежие. Последняя версия PostgreSQL — 9.4, а в контейнерах что вы отправили версии 9.3
        У меня возникли небольшие сложности в работе с версией 9.3, но может быть — это я что-то не так делаю
          0
          Ничего ведь не мешает вынести postgres в отдельный контейнер?..
        0
        Вот еще интересный проект нашелся — github.com/komoot/photon
        Вообще были эксперименты по запахиванию базы OSM сразу в эластик, даже что-то получалось и поживее чем Postgres. Надо посмотреть что там спустя 2 года происходит.
          0
          Спасибо за ссылку. В ближайшее время постараюсь провести тестирование, что будет быстрее: геокодер с использованием PostgreSQL(postgis) или elasticsearch
            +1
            Вот геокодер на ElasticSearch, написанный на коленке для одного из проектов: github.com/ei-grad/geocoder. В итоге используем что-то другое, но этот вроде неплохо работал.

            Feedback welcome.
              +1
              photon для построения индекса вроде тоже PostGIS использует.

              Раз уж это тред геокодеров — вот попробуйте и мой. github.com/kiselev-dv/gazetteer
                0
                Обязательно на днях попробую=)
                Можно будет ещё проверить что же быстрее выполняет запрос.
                  0
                  Вот тут можно живьем инсталляцию покрутить. osm.me
            +1
            обратное геокодирование доступно?..
              +1
              Да, доступно. Вот пример:
              Request: nominatim.openstreetmap.org/reverse?format=json&lat=46.4846121&lon=30.7325586

              Response:
              {"place_id":"91403255","licence":"Data © OpenStreetMap contributors, ODbL 1.0. http:\/\/www.openstreetmap.org\/copyright","osm_type":"way","osm_id":"160458343","lat":"46.48490415","lon":"30.7323209604386","display_name":"23, Преображенская улица, Одесса, Приморский район, Одесса, Одесская область, 65082, Украина","address":{"house_number":"23","road":"Преображенская улица","city":"Одесса","county":"Приморский район","state":"Одесская область","postcode":"65082","country":"Украина","country_code":"ua"}}
              
              • UFO just landed and posted this here
                  0
                  Да, должна эту штука помочь.
                  Можно сделать ещё проще: установить postgreSQL, postgis и Osm2pgsql. Этих программных продуктов должно хватит чтобы импортировать карту OSM в БД, а дальше запросами SQL в PostgreSQL получаете нужные данные. Мне очень понравилась статья Русификация и мультиязычность карт OpenStreetMap, там очень хорошо расписан процесс установки карт, советую прочитать.
                  И ещё один вариант: загружаете карту OSM с сайта туц в формате *.osm.bz2(это архив с картой в формате XML), потом парсите этот XML файл с помощью вашего любимого языка=). Вот ссылка на архитектуру OSM XML карты
                  0
                  А как работаете с «не правильными» адресами? Например, nominatim отлично обрабатывает «Москва, 2-й рощинский проезд, 8», но не обрабатывает «Москва, рощинский 2-й проезд, 8»… Про МКАД nominatim, похоже, вообще ничего не знает: «Москва, 39-й км МКАД»… По этим причинам у нас не получилось использовать его в продакшене (((
                    0
                    Тут уж ничего не поделать, opensorce продукты — они такие. Зато с этими задачами легко справляется такие гиганты как Yandex map и Google map.
                      0
                      Номинатим такие адреса очень не любит.

                      Вот: «Москва, рощинский 2-й проезд, 8»
                      osm.me/#!/ru/map/5/57.78623/52.99805/q/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0,%20%D1%80%D0%BE%D1%89%D0%B8%D0%BD%D1%81%D0%BA%D0%B8%D0%B9%202-%D0%B9%20%D0%BF%D1%80%D0%BE%D0%B5%D0%B7%D0%B4,%208/

                      «Москва, 39-й км МКАД» тоже находится, но мкад и вбит в осм по сегментам, интерполировать киллометры мой подопечный пока не умеет.
                      osm.me/#!/ru/id/hghnet-2919500296-m716947792/map/14/55.59932/37.5117/q/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0,%2039-%D0%B9%20%D0%BA%D0%BC%20%D0%9C%D0%9A%D0%90%D0%94/
                      0
                      Ух ты, в OSM уже и номера домов есть :-/ Надо вылезать из разморозки.

                      PS Посмотрел свой район, номера у 90% домов есть, а при поиске улицы Ленина почему то только её десятую часть находит-подсвечивает.
                        0
                        А imposm3 не подошел бы для импорта базы?

                        В описании пишут, что импорт 20гб planet PBF выполняется за 6.5 часов, а osm2pgsql грузит аналогичный файл за 2-8 дней.
                          0
                          Спасибо за софтину, не знал о ней.
                          Для импортирования данных у номинатима штатно работает osm2pgsql, а переписывать загарузчик не хочетя. Да и основные тормоза osm2pgsq появляются когда база настроенна не оптимально, а с правильной настройкой бд — произоводительности импортирования возрастает.
                          0
                          Сколько заняла база Украины в БД?
                            0
                            База данных заняла 5399 MB.
                            Это с учётом того, что за пару месяцев собрались логи.
                              0
                              Ясно, спасибо. Пока ждал ответа развернул БД Украины+России. Заняла в районе 35 Гигбайт.
                                0
                                Не поделитесь образом виртуалки?)
                                  0
                                  Нет, делал для теста.
                                  Все просто. Качаем карты отсюда http://download.geofabrik.de (как и указано в посте)

                                  Потом объединяем по-парно (сразу несколько файлов нельзя, только по два за несколько проходов):

                                  #/usr/src/Nominatim-2.4.0/utils/osmosis  --read-pbf file=russia-latest.osm.pbf --read-pbf file=ukraine-latest.osm.pbf --merge --write-pbf omitmetadata=true file=rus-ukr.osm.pbf
                                    0
                                    Спасибо!
                                    Наверное, вначале попробую через их апи, с кешированием
                                      0
                                      На openstreetmaps Nominatim с ограничениями, насколько я помню один запрос в секунду. То есть для поиграться подойдет, а если серьезней, лучше развернуть свой.

                                      ps. С таким ограничением не только кеширование нужно, а система управления распределения очереди задач (например celery, если python, ограничение запуска следующей задачи: http://docs.celeryproject.org/en/latest/userguide/tasks.html#Task.rate_limit ). То есть ограничить частоту запросов к серверам openstreetmaps.org.
                                        0
                                        спасибо, так и думал делать. Хотя, все больше склоняюсь к «своему». Проблема в том, что «заказчик», в рамках задачи которого это нужно, начинает сливаться :)

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