Skip to content

Commit

Permalink
Use aiohttp instead of wsgi and flask
Browse files Browse the repository at this point in the history
  • Loading branch information
denisbondar committed Aug 2, 2021
1 parent 2f5d9b3 commit 1522df8
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 80 deletions.
7 changes: 3 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ FROM python:3.8-alpine
RUN mkdir -p /app/cache
WORKDIR /app
COPY --from=base /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
COPY --from=base /usr/local/bin/uwsgi /usr/local/bin/uwsgi
COPY . /app
COPY ./*.py /app/

VOLUME /app/cache
VOLUME /var/run/strava.sock
EXPOSE 9000
EXPOSE 8080

CMD ["uwsgi", "--ini", "wsgi.ini"]
CMD ["python3", "web.py"]
72 changes: 44 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@
их в приложении OsmAnd в качестве оффлайн карты или в приложении JOSM также в качестве
слоя, помогающего при картографировании.

Скрипт работает в двух режимах: режим загрузки тайлов в кэш и режим выдачи тайлов из кэша по протоколу HTTP.

## Запуск в Docker контейнере

Следующие команды содержат параметр `--volume` указывающий на каталог на диске,
в которой будет смонтирован каталог с кэшем контейнера. Перед тем, как продолжить,
этот каталог необходимо создать:
```bash
mkdir -p /var/strava-cache
```

### Запуск построителя кэша

Функция построения (прогрева) кэша проверяет наличие тайлов в кэше в заданной
области географических координат и в заданном диапазоне масштабов. Если тайл
отсутствует - он загружается с CDN-серверов Strava и сохраняется в кэше.
отсутствует он загружается с CDN-серверов Strava и сохраняется в кэше.

Для запуска построителя кэша достаточно выполнить команду `python main.py`
в Docker-контейнере следующим образом:
Expand All @@ -26,60 +35,65 @@ docker run --rm \
python main.py
```

После того, как построитель кэша отработает - работа контейнера будет завершена.
После того как построитель кэша отработает работа контейнера будет завершена.

**Стоит учитывать**, что одна итерация построителя кэша ограничена 6000 тайлами.
Это связано с лимитом на CDN CloudFront. Прежде чем запускать построитель для
следующей партии тайлов, следует подождать минут 10, иначе CDN заблокирует доступ
для вашей учетной записи на какое-то время.
следующей партии тайлов, следует подождать несколько минут, иначе CDN может
заблокировать доступ для вашей учетной записи на какое-то время.

#### Значения переменных в приведенных примерах

В качестве значений для переменных окружения `KEY_PAIR_ID`, `SIGNATURE`, `POLICY`
необходимо указать соответствующие значения, полученные из cookie на сайте
https://www.strava.com/heatmap.
https://www.strava.com/heatmap. Для этого аутентифицируйтесь на сайте а затем
найдите в cookie домена strava.com переменные
`CloudFront-Key-Pair-Id`, `CloudFront-Policy`, `CloudFront-Signature`

Если у вас нет учётной записи на strava.com, то вы сможете загрузить только тайлы
масштаба не более 11.

### Запуск WSGI HTTP-сервера
### Запуск HTTP-сервера

Для запуска wsgi-модуля, принимающего http-запросы вида `http://127.0.0.1:9000/z/x/y.png`, запустите
Для запуска web-модуля, принимающего http-запросы вида `http://127.0.0.1:8080/z/x/y.png`, запустите
контейнер *без указания команды* следующим образом:

```bash
docker run --rm \
--volume /var/strava-cache:/app/cache \
--publish 127.0.0.1:9000:9000 \
--publish 127.0.0.1:8080:8080 \
--env KEY_PAIR_ID=CloudFront-Key-Pair-Id_from_cookies \
--env SIGNATURE=CloudFront-Signature_from_cookies \
--env POLICY=CloudFront-Policy_from_cookies \
--name strava-heatmap-cache \
denisbondar/strava-heatmap-cache
```

Контейнер с wsgi-модулем будет работать постоянно. В конфигурации указан порт 9000,
Контейнер с web-модулем будет работать постоянно. В конфигурации выше указан порт 8080,
на котором принимаются http-подключения. Вы можете изменить его на более подходящий
для вас. Например: `--publish 127.0.0.1:80:9000` будет принимать подключение на 80 порту.
для вас, например, `--publish 127.0.0.1:80:8080` будет принимать подключение на 80 порту.

Если Вам зачем-то понадобилось открыть доступ к своему тайловому кэшу в интернет,
то вам нужно будет использовать nginx в качестве фронтенда к wsgi-модулю.
то вам желательно использовать nginx в качестве фронтенда к web-модулю.

#### Добавление в конфигурацию стека GNINX сервера

Пример конфигурации nginx для wsgi (файл /etc/nginx/conf.d/strava.conf):
```
upstream strava_heatmap {
server 127.0.0.1:9000;
}
В этом нет необходимости, если вы собираетесь работать с кэшем локально, не через интернет.

Варианты использования кэша, приведенные ниже, рассчитаны на использование web-модуля,
работающего на порту 8080 (без NGINX).

Пример конфигурации nginx в качестве реверсивного прокси (файл /etc/nginx/conf.d/strava.conf):
```
server {
listen 80;
server_name <доменное_имя_вашего_сервера>;
location / {
include uwsgi_params;
uwsgi_pass strava_heatmap;
proxy_pass http://127.0.0.1:8080;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
Expand All @@ -89,15 +103,17 @@ server {
### Использование в качествео оффлайн карты OsmAnd

1. Создайте онлайн карту в OsmAnd. Назовите ее, например, **Strava Heatmap**.
Укажите диапазон масштаба 8..16. Можно указать URL бесплатных тайлов - он
Укажите диапазон масштаба 8..16. Можно указать URL бесплатных тайлов он
будет использоваться, если OsmAnd не найдет тайлов в кэше.
`https://heatmap-external-a.strava.com/tiles/ride/bluered/{0}/{1}/{2}.png`.
[Подробнее на сайте OsmAnd](https://osmand.net/features/online-maps-plugin).

2. Скопируйте каталог с кэшем на ваше андроид устройство в каталог
`/Android/data/net.osmand/files/tiles/Strava Heatmap`.
2. Скопируйте каталог с кэшем на Ваше андроид-устройство в каталог
`/Android/data/net.osmand/files/tiles/Strava Heatmap` или одноименный каталог,
если вы перенесли каталог в другое место (например, на SD-карту).
Так как файлов может быть очень много, то лучше создайте архив на компьютере,
скопируйте его на смартфон и там разархивируйте.
скопируйте его на смартфон и там разархивируйте. Самый простой способ — переименовать
каталог cache в Strava Heatmap и заархивировать его, затем переименовать обратно в cache.
Структура каталогов в результате должна быть примерно такой:
`...net.osmand/files/tiles/Strava Heatmap/7/74/`

Expand All @@ -110,17 +126,17 @@ server {
1. В JOSM в меню Слои - Настройки слоёв... в нижней части окна в списке
"Выбранные" нажмите кнопку **+TMS** и введите в п.4 готовый URL следующего вида:
`tms[16]:file:///var/strava-cache/{zoom}/{x}/{y}png.tile`. Путь к кэшу указан
такой же, как и volume в примере запуска с использованием Docker, но у вас он
может быть каким угодно. В п.5 введите название слоя, например, `Strava Heatmap`.
Нажмите **ОК** в окне добавления подложки и **ОК** в окне настрек.
такой же, как и для volume в примере запуска с использованием Docker, но у вас он
может быть другим. В п.5 введите название слоя, например, `Strava Heatmap`.
Нажмите **ОК** в окне добавления подложки и **ОК** в окне настроек.

2. В меню Слои выберите слой **Strava Heatmap** - новый слой будет добавлен и
2. В меню Слои выберите слой **Strava Heatmap** новый слой будет добавлен и
тайлы будут отображены на карте.

3. Рекомендуется немного размыть слой, т.к. границы тепловой карты могут быть
слишком резкими. Нажмите в списке слоев на слой **Strava Heatmap**, затем внизу
нажмите кнопку **Изменить видимость выбранного слоя** и настройте максимально
комфортную резкость и другие параметры отобраения по необходимости.
комфортную резкость и другие параметры отображения по необходимости.

### Использования в качестве overlay в BRouter

Expand All @@ -140,7 +156,7 @@ server {
2. Справа на панели в списке слоёв (Layers) нажмите кнопку Custom layers.

3. В поле Custom layer name укажите, например, Strava Heatmap, а в поле
Custom layer URL укажите `http://127.0.0.1:9000/{z}/{x}/{y}.png`, если вы используете
Custom layer URL укажите `http://127.0.0.1:8080/{z}/{x}/{y}.png`, если вы используете
настройки, указанные по умолчанию в этой инструкции. Иначе номер порта или адрес
могут быть другими.

Expand Down
6 changes: 4 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ async def download_tile(self, tile: Tile):
elif response.status == 404:
await self.cache.write(tile, EMPTY_TILE)
else:
print("For %r received an unexpected status code %d" % (tile, response.status))
print("For %r received an unexpected status code %d: %s" % (tile,
response.status,
await response.text()))
except client_exceptions.ServerDisconnectedError as e:
raise PermissionError("It is necessary to lower the value of the semaphore. %s" % e) from e
except client_exceptions.ClientOSError as e:
Expand Down Expand Up @@ -214,7 +216,7 @@ def warm_up(self,
warmer.warm_up(GeoPoint(46.90946, 30.19284),
GeoPoint(46.10655, 31.39070),
range(7, 17),
max_tiles=6000)
max_tiles=8000)
except PermissionError as e:
print("Error: %s" % e)
print("Spent in", round((time() - start_time), 2), "seconds.")
2 changes: 0 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
uwsgi
flask
aiohttp
aiofiles
28 changes: 28 additions & 0 deletions web.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from main import Cache, Tile, StravaFetcher, cache_dir, auth_data
from aiohttp import web

cache = Cache(cache_dir)
fetcher = StravaFetcher(auth_data, cache)
routes = web.RouteTableDef()


@routes.get(r'/{z:\d+}/{x:\d+}/{y:\d+}.png')
async def get_tile(request: web.Request) -> web.StreamResponse:
z = int(request.match_info['z'])
x = int(request.match_info['x'])
y = int(request.match_info['y'])

if z < 7 or z > 16:
return web.Response(status=404, reason='Zoom is out of range')

tile = Tile(x, y, z)
if not cache.tile_already_in_cache(tile):
return web.Response(status=404, reason='Not in cache')

return web.FileResponse(path=cache.abs_tile_path(tile))


if __name__ == '__main__':
app = web.Application()
app.add_routes(routes)
web.run_app(app, port=8080)
14 changes: 0 additions & 14 deletions wsgi.ini

This file was deleted.

30 changes: 0 additions & 30 deletions wsgi.py

This file was deleted.

0 comments on commit 1522df8

Please sign in to comment.