Добавил форму для загрузки данных с LyngSat
This commit is contained in:
420
ASYNC_LYNGSAT_GUIDE.md
Normal file
420
ASYNC_LYNGSAT_GUIDE.md
Normal file
@@ -0,0 +1,420 @@
|
||||
# Руководство по асинхронному заполнению данных Lyngsat
|
||||
|
||||
## Обзор
|
||||
|
||||
Система заполнения данных Lyngsat теперь работает асинхронно с использованием Celery. Это позволяет:
|
||||
- Не блокировать веб-интерфейс во время долгих операций
|
||||
- Отслеживать прогресс выполнения задачи в реальном времени
|
||||
- Просматривать детальные логи обработки
|
||||
- Получать уведомления о завершении задачи
|
||||
|
||||
## Архитектура
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Django │─────▶│ Celery │─────▶│ Redis │
|
||||
│ Web App │ │ Worker │ │ Broker │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌─────────────┐
|
||||
└─────────────▶│ PostgreSQL │
|
||||
│ Database │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## Установка и настройка
|
||||
|
||||
### 1. Установка зависимостей
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Новые зависимости:
|
||||
- `celery>=5.4.0` - асинхронная обработка задач
|
||||
- `django-celery-results>=2.5.1` - хранение результатов в БД
|
||||
|
||||
### 2. Применение миграций
|
||||
|
||||
```bash
|
||||
cd dbapp
|
||||
python manage.py migrate
|
||||
```
|
||||
|
||||
Это создаст таблицы для хранения результатов Celery.
|
||||
|
||||
### 3. Запуск Redis
|
||||
|
||||
Redis используется как брокер сообщений для Celery.
|
||||
|
||||
#### Вариант 1: Docker Compose (рекомендуется)
|
||||
```bash
|
||||
docker-compose up -d redis
|
||||
```
|
||||
|
||||
#### Вариант 2: Локальная установка
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install redis-server
|
||||
sudo systemctl start redis
|
||||
|
||||
# macOS
|
||||
brew install redis
|
||||
brew services start redis
|
||||
|
||||
# Проверка
|
||||
redis-cli ping
|
||||
# Должно вернуть: PONG
|
||||
```
|
||||
|
||||
### 4. Запуск FlareSolver
|
||||
|
||||
FlareSolver необходим для обхода защиты Cloudflare.
|
||||
|
||||
```bash
|
||||
docker-compose up -d flaresolverr
|
||||
```
|
||||
|
||||
Или отдельно:
|
||||
```bash
|
||||
docker run -d -p 8191:8191 --name flaresolverr ghcr.io/flaresolverr/flaresolverr:latest
|
||||
```
|
||||
|
||||
### 5. Запуск Celery Worker
|
||||
|
||||
#### Вариант 1: Используя скрипт
|
||||
```bash
|
||||
cd dbapp
|
||||
./start_celery_worker.sh
|
||||
```
|
||||
|
||||
#### Вариант 2: Напрямую
|
||||
```bash
|
||||
cd dbapp
|
||||
celery -A dbapp worker --loglevel=info
|
||||
```
|
||||
|
||||
#### Вариант 3: В фоновом режиме (Linux/macOS)
|
||||
```bash
|
||||
cd dbapp
|
||||
celery -A dbapp worker --loglevel=info --logfile=logs/celery_worker.log --detach
|
||||
```
|
||||
|
||||
## Использование
|
||||
|
||||
### 1. Запуск задачи через веб-интерфейс
|
||||
|
||||
1. Откройте страницу действий: `http://localhost:8000/actions/`
|
||||
2. Нажмите "Заполнить данные Lyngsat"
|
||||
3. Выберите спутники и регионы
|
||||
4. Нажмите "Заполнить данные"
|
||||
5. Вы будете перенаправлены на страницу отслеживания прогресса
|
||||
|
||||
### 2. Отслеживание прогресса
|
||||
|
||||
На странице статуса задачи вы увидите:
|
||||
- **Прогресс-бар** с процентом выполнения
|
||||
- **Текущий статус** (например, "Обработка Astra 4A...")
|
||||
- **Состояние задачи** (PENDING, PROGRESS, SUCCESS, FAILURE)
|
||||
- **Результаты** после завершения:
|
||||
- Количество обработанных спутников
|
||||
- Количество обработанных источников
|
||||
- Количество созданных записей
|
||||
- Количество обновленных записей
|
||||
- Список ошибок (если есть)
|
||||
|
||||
Страница автоматически обновляется каждые 2 секунды.
|
||||
|
||||
### 3. Просмотр логов
|
||||
|
||||
Логи Celery worker содержат детальную информацию о процессе:
|
||||
|
||||
```bash
|
||||
# Просмотр логов в реальном времени
|
||||
tail -f dbapp/logs/celery_worker.log
|
||||
|
||||
# Поиск по логам
|
||||
grep "Task" dbapp/logs/celery_worker.log
|
||||
grep "ERROR" dbapp/logs/celery_worker.log
|
||||
```
|
||||
|
||||
Формат логов:
|
||||
```
|
||||
[2024-01-15 10:30:45: INFO/MainProcess][lyngsatapp.fill_lyngsat_data_async(abc123)] [Task abc123] Начало обработки данных Lyngsat
|
||||
[2024-01-15 10:30:45: INFO/MainProcess][lyngsatapp.fill_lyngsat_data_async(abc123)] [Task abc123] Спутники: Astra 4A, Hotbird 13G
|
||||
[2024-01-15 10:30:46: INFO/MainProcess][lyngsatapp.fill_lyngsat_data_async(abc123)] [Task abc123] Получено данных по 2 спутникам
|
||||
[2024-01-15 10:31:00: INFO/MainProcess][lyngsatapp.fill_lyngsat_data_async(abc123)] [Task abc123] Обработка спутника 1/2: Astra 4A
|
||||
```
|
||||
|
||||
## Технические детали
|
||||
|
||||
### Структура задачи
|
||||
|
||||
**Файл**: `dbapp/lyngsatapp/tasks.py`
|
||||
|
||||
```python
|
||||
@shared_task(bind=True, name='lyngsatapp.fill_lyngsat_data_async')
|
||||
def fill_lyngsat_data_task(self, target_sats, regions=None):
|
||||
# Логирование начала
|
||||
# Обновление прогресса
|
||||
# Вызов функции заполнения
|
||||
# Сохранение результата в кеш
|
||||
# Обработка ошибок
|
||||
```
|
||||
|
||||
### Обновление прогресса
|
||||
|
||||
Функция `fill_lyngsat_data` теперь принимает callback `update_progress`:
|
||||
|
||||
```python
|
||||
def update_progress(current, total, status):
|
||||
self.update_state(
|
||||
state='PROGRESS',
|
||||
meta={
|
||||
'current': current,
|
||||
'total': total,
|
||||
'status': status
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### API для проверки статуса
|
||||
|
||||
**Endpoint**: `/api/lyngsat-task-status/<task_id>/`
|
||||
|
||||
**Ответ**:
|
||||
```json
|
||||
{
|
||||
"task_id": "abc123",
|
||||
"state": "PROGRESS",
|
||||
"status": "Обработка Astra 4A...",
|
||||
"current": 1,
|
||||
"total": 2,
|
||||
"percent": 50
|
||||
}
|
||||
```
|
||||
|
||||
### Логирование
|
||||
|
||||
Используется стандартный модуль `logging` Python:
|
||||
|
||||
```python
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.info(f"[Task {task_id}] Начало обработки")
|
||||
logger.debug(f"[Task {task_id}] Детальная информация")
|
||||
logger.warning(f"[Task {task_id}] Предупреждение")
|
||||
logger.error(f"[Task {task_id}] Ошибка", exc_info=True)
|
||||
```
|
||||
|
||||
## Настройки Celery
|
||||
|
||||
**Файл**: `dbapp/dbapp/settings/base.py`
|
||||
|
||||
```python
|
||||
# Брокер сообщений
|
||||
CELERY_BROKER_URL = 'redis://localhost:6379/0'
|
||||
|
||||
# Хранение результатов
|
||||
CELERY_RESULT_BACKEND = 'django-db'
|
||||
|
||||
# Таймауты
|
||||
CELERY_TASK_TIME_LIMIT = 30 * 60 # 30 минут
|
||||
CELERY_TASK_SOFT_TIME_LIMIT = 25 * 60 # 25 минут
|
||||
|
||||
# Отслеживание прогресса
|
||||
CELERY_TASK_TRACK_STARTED = True
|
||||
```
|
||||
|
||||
## Мониторинг и отладка
|
||||
|
||||
### Flower - веб-интерфейс для мониторинга Celery
|
||||
|
||||
Установка:
|
||||
```bash
|
||||
pip install flower
|
||||
```
|
||||
|
||||
Запуск:
|
||||
```bash
|
||||
celery -A dbapp flower
|
||||
```
|
||||
|
||||
Откройте: `http://localhost:5555`
|
||||
|
||||
### Проверка статуса задачи через Django shell
|
||||
|
||||
```python
|
||||
python manage.py shell
|
||||
|
||||
from celery.result import AsyncResult
|
||||
|
||||
task_id = 'abc123'
|
||||
task = AsyncResult(task_id)
|
||||
|
||||
print(f"State: {task.state}")
|
||||
print(f"Info: {task.info}")
|
||||
print(f"Result: {task.result}")
|
||||
```
|
||||
|
||||
### Очистка старых результатов
|
||||
|
||||
```bash
|
||||
# Удалить результаты старше 1 дня
|
||||
python manage.py celery_results_cleanup --days=1
|
||||
```
|
||||
|
||||
## Решение проблем
|
||||
|
||||
### Проблема: Worker не запускается
|
||||
|
||||
**Решение**:
|
||||
1. Проверьте, что Redis запущен: `redis-cli ping`
|
||||
2. Проверьте настройки в `.env`: `CELERY_BROKER_URL`
|
||||
3. Проверьте логи: `tail -f logs/celery_worker.log`
|
||||
|
||||
### Проблема: Задача зависла в состоянии PENDING
|
||||
|
||||
**Решение**:
|
||||
1. Проверьте, что worker запущен: `ps aux | grep celery`
|
||||
2. Перезапустите worker
|
||||
3. Проверьте соединение с Redis
|
||||
|
||||
### Проблема: Задача завершается с ошибкой
|
||||
|
||||
**Решение**:
|
||||
1. Проверьте логи worker
|
||||
2. Проверьте, что FlareSolver запущен: `curl http://localhost:8191/v1`
|
||||
3. Проверьте, что спутники существуют в базе данных
|
||||
|
||||
### Проблема: Прогресс не обновляется
|
||||
|
||||
**Решение**:
|
||||
1. Откройте консоль браузера (F12) и проверьте ошибки
|
||||
2. Проверьте, что API endpoint доступен: `/api/lyngsat-task-status/<task_id>/`
|
||||
3. Очистите кеш браузера
|
||||
|
||||
## Производственное развертывание
|
||||
|
||||
### Systemd сервис для Celery Worker
|
||||
|
||||
Создайте файл `/etc/systemd/system/celery-worker.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Celery Worker for Django Lyngsat
|
||||
After=network.target redis.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=www-data
|
||||
Group=www-data
|
||||
WorkingDirectory=/path/to/dbapp
|
||||
Environment="PATH=/path/to/venv/bin"
|
||||
ExecStart=/path/to/venv/bin/celery -A dbapp worker --loglevel=info --logfile=/var/log/celery/worker.log --detach
|
||||
ExecStop=/path/to/venv/bin/celery -A dbapp control shutdown
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Запуск:
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable celery-worker
|
||||
sudo systemctl start celery-worker
|
||||
sudo systemctl status celery-worker
|
||||
```
|
||||
|
||||
### Supervisor (альтернатива)
|
||||
|
||||
Установка:
|
||||
```bash
|
||||
sudo apt-get install supervisor
|
||||
```
|
||||
|
||||
Конфигурация `/etc/supervisor/conf.d/celery.conf`:
|
||||
```ini
|
||||
[program:celery-worker]
|
||||
command=/path/to/venv/bin/celery -A dbapp worker --loglevel=info
|
||||
directory=/path/to/dbapp
|
||||
user=www-data
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/log/celery/worker.log
|
||||
stderr_logfile=/var/log/celery/worker_error.log
|
||||
```
|
||||
|
||||
Запуск:
|
||||
```bash
|
||||
sudo supervisorctl reread
|
||||
sudo supervisorctl update
|
||||
sudo supervisorctl start celery-worker
|
||||
```
|
||||
|
||||
## Дополнительные возможности
|
||||
|
||||
### Периодические задачи (Celery Beat)
|
||||
|
||||
Для автоматического обновления данных по расписанию:
|
||||
|
||||
1. Установите `django-celery-beat`:
|
||||
```bash
|
||||
pip install django-celery-beat
|
||||
```
|
||||
|
||||
2. Добавьте в `INSTALLED_APPS`:
|
||||
```python
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
'django_celery_beat',
|
||||
]
|
||||
```
|
||||
|
||||
3. Примените миграции:
|
||||
```bash
|
||||
python manage.py migrate django_celery_beat
|
||||
```
|
||||
|
||||
4. Создайте периодическую задачу через админ-панель Django
|
||||
|
||||
5. Запустите beat scheduler:
|
||||
```bash
|
||||
celery -A dbapp beat --loglevel=info
|
||||
```
|
||||
|
||||
### Уведомления по email
|
||||
|
||||
Добавьте в задачу отправку email при завершении:
|
||||
|
||||
```python
|
||||
from django.core.mail import send_mail
|
||||
|
||||
@shared_task(bind=True)
|
||||
def fill_lyngsat_data_task(self, target_sats, regions=None):
|
||||
# ... обработка ...
|
||||
|
||||
# Отправка email
|
||||
send_mail(
|
||||
'Задача Lyngsat завершена',
|
||||
f'Обработано {stats["total_satellites"]} спутников',
|
||||
'noreply@example.com',
|
||||
['admin@example.com'],
|
||||
)
|
||||
```
|
||||
|
||||
## Заключение
|
||||
|
||||
Асинхронная обработка данных Lyngsat обеспечивает:
|
||||
- ✅ Неблокирующий веб-интерфейс
|
||||
- ✅ Отслеживание прогресса в реальном времени
|
||||
- ✅ Детальное логирование
|
||||
- ✅ Масштабируемость (можно запустить несколько workers)
|
||||
- ✅ Надежность (автоматический retry при ошибках)
|
||||
|
||||
Для получения дополнительной помощи обратитесь к документации:
|
||||
- [Celery Documentation](https://docs.celeryproject.org/)
|
||||
- [Django Celery Results](https://django-celery-results.readthedocs.io/)
|
||||
Reference in New Issue
Block a user