Files
2026-09-21 06:29:08 +03:00

124 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tile Server
ASP.NET Core сервер векторных тайлов для клиентов **MapLibre GL**.
Ежедневно (и при старте) воркер:
1. Скачивает все настроенные OSM-extract’ы с Geofabrik (и любых других HTTP-ссылок на `.osm.pbf`).
2. Собирает из них OpenMapTiles MBTiles через [planetiler-openmaptiles](https://github.com/openmaptiles/planetiler-openmaptiles).
3. Отдаёт тайлы, TileJSON и стили карты.
## Что нужно
- .NET 8 SDK
- **Java 21+** в `PATH` (или путь в `TileServer:JavaPath`) — без Java тайлы не соберутся, уже готовые MBTiles сервер всё равно отдаст
- Диск: 5–10× размер PBF. ЦФО до **z15** — ориентир несколько ГБ готового MBTiles плюс столько же на staging во время сборки
- RAM: контейнер ~12g. `TileServer:JvmMaxHeap` — только Java heap, держите **~⅓ лимита** (по умолчанию `4g`). Остальное — mmap/файлы Planetiler и Kestrel. Код **137** = OOM killer, не переполнение `-Xmx`.
Тайлы собираются через OpenMapTiles. Схема рассчитана на z0–z14 (дефолт MapTiler/Planetiler). Жёсткий потолок **planetiler-openmaptiles 3.16 — z15**; z16+ этот JAR не умеет. Ближе z15 MapLibre overzoom’ит те же тайлы до z18.
Первая сборка ЦФО занимает часы. Для быстрой проверки временно поставьте Monaco:
```json
"Url": "https://download.geofabrik.de/europe/monaco-latest.osm.pbf"
```
## Запуск
```bash
dotnet run --project src/TileServer.Api
```
Откройте http://localhost:5088 — тестовая карта, выбор источника и стиля.
```bash
docker compose up -d --build
```
Сервис слушает **51300** (внутри контейнера 8080). Данные (PBF, MBTiles, стили, ключи) — Docker volume `tile-server-data`, деплой кода его не затирает. Не вызывайте `docker compose down -v`.
Если на сервере уже есть `./data`, один раз перенесите:
```bash
docker run --rm -v "$(pwd)/data:/from:ro" -v tile-server-data:/to alpine sh -c "cp -a /from/. /to/"
docker compose up -d --build
```
## API
| Метод | URL | Назначение |
| --- | --- | --- |
| `GET` | `/api/v1/tiles/{source}/{z}/{x}/{y}.pbf` | векторный тайл (MapLibre XYZ) |
| `GET` | `/api/v1/tiles/{source}.json` | TileJSON |
| `GET` | `/api/v1/styles` | список стилей |
| `GET` | `/api/v1/styles/{name}?source={source}` | MapLibre style JSON |
| `PUT` | `/api/v1/styles/{name}` | добавить/обновить стиль |
| `GET` | `/api/v1/sources` | extract’ы и статус воркера |
| `PUT` | `/api/v1/sources/{id}` | добавить регион (ещё одна ссылка на PBF) |
| `POST` | `/api/v1/sync` | прогнать все extract’ы сейчас |
| `POST` | `/api/v1/sync/{id}` | прогнать один extract |
| `GET` | `/` | демо MapLibre |
Алиасы без `/api/v1`: `/tiles/{source}/{z}/{x}/{y}.pbf`.
## Несколько регионов
В `appsettings.json``TileServer:Extracts` можно перечислить сколько угодно выгрузок. Воркер проходит **все** `Enabled: true` по очереди (чтобы не упереться в RAM).
```json
"Extracts": [
{
"Id": "central-fed-district",
"Name": "Центральный федеральный округ",
"Url": "https://download.geofabrik.de/russia/central-fed-district-latest.osm.pbf",
"Center": [37.6173, 55.7558]
},
{
"Id": "northwestern-fed-district",
"Name": "Северо-Западный федеральный округ",
"Url": "https://download.geofabrik.de/russia/northwestern-fed-district-latest.osm.pbf",
"Center": [30.3141, 59.9386]
}
]
```
То же самое в runtime: `PUT /api/v1/sources/{id}` (пишет `data/extracts.json`, переживает рестарт).
Расписание: cron `TileServer:Sync:Cron`, по умолчанию `0 3 * * *` UTC. Если PBF не изменился (HTTP 304) и MBTiles уже есть — пересборка пропускается, **кроме случая когда в конфиге MaxZoom больше, чем в текущем тайсете** (после поднятия z14→z15 сборка пойдёт сама).
Клиенты в TileJSON/стиле видят maxzoom собранной пирамиды (14/15): MapLibre сам растягивает эти тайлы ближе. Если кто-то всё же запросит z16–18, сервер нарежет их из родителя. Вне ЦФО отдаётся 204, не 404.
## Стили
Кладёте `data/styles/{name}.json` (MapLibre Style Spec v8, схема слоёв OpenMapTiles) или делаете `PUT /api/v1/styles/{name}`.
Клиент запрашивает стиль по имени:
```
GET /api/v1/styles/osm-bright?source=central-fed-district
```
Сервер подставляет TileJSON выбранного источника. Из коробки: `osm-bright`, `dark`, `positron`.
Пример источника в MapLibre:
```js
const map = new maplibregl.Map({
container: "map",
style: "http://localhost:5088/api/v1/styles/osm-bright?source=central-fed-district",
center: [37.6173, 55.7558],
zoom: 6
});
```
## Архитектура
```
Api контроллеры, демо, ProblemDetails
Application sync, tiles, styles, extracts
Domain extract, tile coordinate, ошибки
Infrastructure загрузка PBF, Planetiler, MBTiles/SQLite, файловые стили, hosted worker
```
Данные по умолчанию: `data/` в корне репозитория (`../../data` относительно проекта API). В проде задайте `TileServer__DataDirectory`.