# OSRM routing engine (self-hosted) — #39 Self-hosted [OSRM](https://project-osrm.org/) для site-finder `/analyze`: реальные дорожные / пешие расстояния до POI вместо straight-line `ST_Distance(geography)`. > **Scope этого PR — INFRA ONLY.** Здесь стоит контейнер + build-скрипт + healthcheck. > Интеграция в `/analyze` (замена `ST_Distance` на OSRM `route`/`table`) — отдельный > follow-up (A2 изохроны, A3 per-category routing-decay). Backend пока к osrm НЕ ходит. ## Архитектура ``` backend ──http://osrm:5000──▶ osrm (osrm-routed --algorithm mld) │ volume ./data/osrm:/data └─ /data/sverdlovsk.osrm* (MLD-граф, ~ХХХ MB) ``` - Compose service `osrm` в `docker-compose.prod.yml`, сеть `default` (project `gendesign`). - **Наружу НЕ публикуется** — нет `ports:`. Достижим только из backend по `http://osrm:5000`. Caddy его не проксирует (routing — internal API, не должен быть публичным). - `mem_limit: 1.5g`, `restart: unless-stopped`. - Граф (`/data/*.osrm*`) НЕ в git (`.gitignore` → `data/osrm/*`). Строится offline на VPS. ## Build / refresh графа Скрипт: [`scripts/build_osrm.sh`](../scripts/build_osrm.sh). Запускается **вручную** на VPS (НЕ часть `deploy.yml` — download+build тяжёлые). ```bash cd /opt/gendesign bash scripts/build_osrm.sh # car-профиль, Свердл-clip (default) ``` ### Источник pbf и решение по региону Geofabrik **не** публикует Свердловскую область отдельно — есть только [Уральский ФО](https://download.geofabrik.de/russia/ural-fed-district-latest.osm.pbf) (≈600 MB). Скрипт по умолчанию (`CLIP=1`) скачивает Ural-FO и **обрезает по bbox Свердл. обл.** через `osmium extract` → легче граф, меньше RAM в runtime. | Режим | Команда | pbf | Граф в RAM (warm) | Когда | |---|---|---|---|---| | **Свердл-clip** (default) | `bash scripts/build_osrm.sh` | clip из Ural-FO | ~0.8–1.2 GB | рекоменд., extensibility на обл | | ЕКБ-tight | `EKB_TIGHT=1 bash scripts/build_osrm.sh` | узкий bbox ЕКБ | ~0.4–0.6 GB | если RAM на VPS критична | | Ural-FO zero-clip | `CLIP=0 bash scripts/build_osrm.sh` | весь Ural-FO | ~1.5 GB+ | если нужен запас на соседние регионы | bbox Свердл (с запасом): `lon 57.2..66.2, lat 56.0..62.0`. ЕКБ-tight: `lon 59.0..62.5, lat 56.2..58.2`. ### Pipeline (MLD, не CH) `--algorithm mld` в compose требует pipeline **extract → partition → customize** (скрипт делает это через тот же `osrm/osrm-backend` образ). `osrm-contract` — это CH-алгоритм, он несовместим с `--algorithm mld`, поэтому НЕ используется. ### Walking-профиль (Phase-2, опционально) Issue хочет оба профиля (car + foot) eventually. Этот PR **car-first**. Пеший граф: ```bash WALK=1 bash scripts/build_osrm.sh # дополнительно соберёт sverdlovsk-foot.osrm* ``` Для пешего routing нужен второй compose-service (он не добавлен в этом PR, чтобы не плодить idle-контейнер пока /analyze не интегрирован). Блок для будущего: ```yaml osrm-walk: image: osrm/osrm-backend:latest restart: unless-stopped command: osrm-routed --algorithm mld --max-table-size 8000 /data/${OSRM_REGION:-sverdlovsk}-foot.osrm volumes: [./data/osrm:/data] mem_limit: 1g healthcheck: test: ["CMD-SHELL", "timeout 3 bash -c '> /var/log/osrm-build.log 2>&1 \ && docker compose -p gendesign -f docker-compose.prod.yml up -d --force-recreate --no-deps osrm ``` Скрипт idempotent: `wget -N` качает только если на сервере новее, граф перестраивается overwrite. ## Развёртывание (что выполняет оркестратор на VPS) ```bash cd /opt/gendesign git fetch origin main && git reset --hard origin/main # подтянуть compose + скрипт # 1. Build графа (~30–50 мин, ~600MB download + ~3GB peak RAM на extract) bash scripts/build_osrm.sh # 2. Поднять контейнер docker compose -p gendesign -f docker-compose.prod.yml up -d osrm # 3. Verify (curl ВНУТРИ образа нет — используем sidecar curl в той же сети) docker run --rm --network gendesign_default curlimages/curl:8 -fsS \ 'http://osrm:5000/route/v1/driving/60.6,56.84;60.65,56.86' # ожидаем JSON: {"code":"Ok","routes":[{...}], ...} ``` ## Healthcheck Compose-healthcheck — TCP-probe порта 5000 через `bash /dev/tcp` (образ `osrm/osrm-backend` НЕ содержит curl/wget, HTTP-probe падал бы на missing binary). Полный route-probe — verify-команда выше (sidecar curl). ## Риски / open - **RAM на Beget VPS**: +~1 GB warm для Свердл-clip. Перед `up -d osrm` проверить свободную RAM (`free -h`). Если жмёт — `EKB_TIGHT=1` (~0.4–0.6 GB) или upgrade plan. - **Build на VPS медленный** (50+ мин). Альтернатива: собрать локально и `scp` `data/osrm/*.osrm*` в `/opt/gendesign/data/osrm/`. - **Размер pbf неточен**: Ural-FO ≈600 MB на скачку; «1.5GB» из issue — оценка по всему ФО + intermediate-файлы на диске во время build (нужно ~5 GB свободного диска).