Django SocketIO Connection Fails After RDS Restart - Как решить проблему с подключением к базе данных?

Я разрабатываю Django-приложение, использующее SocketIO для связи в реальном времени, и столкнулся с проблемой, когда SocketIO-соединения не работают после перезапуска RDS (Relational Database Service), в то время как мои Django HTTP API продолжают работать нормально.

Описание проблемы Мое Django-приложение интегрируется с SocketIO для работы в режиме реального времени. После перезапуска экземпляра RDS HTTP API функционируют нормально, но SocketIO-соединения сталкиваются с проблемами и не могут получить доступ к моделям баз данных. В частности, я получаю ошибки, связанные с подключением к базе данных, при попытке обработать SocketIO-соединения.

Фрагменты кода Вот как я настраиваю свое ASGI-приложение и обрабатываю SocketIO-соединения:

Конфигурация ASGI (asgi.py):

import os
from django.core.asgi import get_asgi_application
import socketio
from backend.socketio import socketio_server

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings.dev')
django_asgi_app = get_asgi_application()
application = socketio.ASGIApp(socketio_server=socketio_server.socketio_server, other_asgi_app=django_asgi_app)

Обработчик соединения сокетаIO:

async def on_connect(self, sid: str, environ: dict):
    try:
        query_string = environ['asgi.scope']['query_string']
        token, chat_id = get_token_chat_id_from_query(query_string=query_string)
        if not token or not chat_id:
            raise ConnectionRefusedError("Invalid connection parameters.")
        
        user = await get_user_from_token(token=token)
        chat_obj = await get_chat_from_id(chat_id=chat_id, user=user)
        await update_all_chat_redis(chat_obj=chat_obj)
        
        async with self.session(sid=sid, namespace=self.namespace) as session:
            session['user_id'] = user.id
            session['chat_id'] = chat_obj.machine_translation_request_id
        
        await self.enter_room(sid=sid, room=chat_id)

    except ConnectionRefusedError as e:
        logger.error(f"Connection refused: {e}")
        raise

    except UserErrors as exc:
        logger.error(f"User error: {exc.message}")
        raise ConnectionRefusedError(exc.message)

    except Exception as e:
        logger.error(f"Unexpected error: {e}")
        raise ConnectionRefusedError("An unexpected error occurred. Please try again later.")

Функция доступа к базе данных (@sync_to_async):

import logging
from django.utils import timezone
from django.db import OperationalError
from yourapp.exceptions import UserErrors

logger = logging.getLogger(__name__)

@sync_to_async
def get_user_from_token(token: str):
    retries = 3
    for attempt in range(retries):
        try:
            token_obj = AccessToken.objects.filter(token=token, expires__gt=timezone.now()).last()
            if not token_obj:
                raise UserErrors("Invalid Token!")
            return token_obj.user
        except OperationalError as e:
            logger.error(f"Database operational error on attempt {attempt + 1}: {e}")
            await asyncio.sleep(2)  # Wait before retrying
        except Exception as e:
            logger.error(f"Unexpected error on attempt {attempt + 1}: {e}")
            if attempt == retries - 1:
                raise
            await asyncio.sleep(2)  # Wait before retrying

Что я пробовал

  • Обработка ошибок: Реализовано подробное протоколирование ошибок в обработчиках SocketIO и функциях доступа к базе данных.
  • Логика повторных попыток: Добавлена логика повторных попыток для операций с базой данных.
  • Интеграция SocketIO: Убедились, что SocketIO правильно интегрирован с Django ASGI. Вопрос. Как решить проблему, когда SocketIO-соединения не работают после перезапуска RDS, в то время как HTTP API продолжают работать правильно? Существуют ли специальные лучшие практики для решения проблем с подключением к базе данных в Django-приложении, использующем SocketIO? Любые рекомендации по улучшению устойчивости или шаги по устранению неполадок были бы очень признательны.
Вернуться на верх