126 lines
6.3 KiB
Markdown
126 lines
6.3 KiB
Markdown
# 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 '</dev/tcp/127.0.0.1/5000' || exit 1"]
|
||
interval: 30s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 40s
|
||
networks: [default]
|
||
```
|
||
|
||
Backend ходил бы к нему по `http://osrm-walk:5000`.
|
||
|
||
### Monthly refresh
|
||
|
||
osm.pbf на Geofabrik обновляется ежедневно. Граф освежать ~ежемесячно:
|
||
|
||
```cron
|
||
0 4 1 * * cd /opt/gendesign && bash scripts/build_osrm.sh >> /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 свободного диска).
|