Б
NodeJS, Socket.io
Проблема
Представьте, что есть 2 пользователя U1 и U2, подключенные к приложению через Socket.io. Алгоритм следующий:
- U1 полностью теряет подключение к Интернету (например, отключает Интернет)
- U2 отправляет сообщение U1.
- U1 еще не получил сообщение, потому что Интернет отключен.
- Сервер обнаруживает разъединение U1 с помощью тайм-аута heartbeat
- U1 подключается к socket.io
- U1 никогда не получает сообщение от U2 - он потерян на шаге 4, я думаю.
Возможное объяснение
Думаю, я понимаю, почему это происходит:
- на шаге 4 Сервер убивает экземпляр сокета и очередь сообщений U1, а также
- Кроме того, на шаге 5 U1 и Сервер создать новое соединение (оно не используется повторно), поэтому даже если сообщение все еще поставлено в очередь, предыдущее соединение все равно потеряно.
Нужна помощь
Как я могу предотвратить такую потерю данных? Я должен использовать listenbeats, потому что я не нахожусь в приложении навсегда. Кроме того, я должен предоставить возможность повторно подключиться, потому что, когда я развертываю новую версию приложения, я хочу нулевое время простоя.
P.S. То, что я называю "сообщение", - это не просто текстовое сообщение, которое я могу хранить в базе данных, но ценное системное сообщение, доставка которого должна быть гарантирована, или пользовательский интерфейс затягивается.
Спасибо!
Дополнение 1
У меня уже есть система учетных записей пользователей. Более того, моя заявка уже сложна. Добавление автономных/онлайн-статусов не поможет, потому что у меня уже есть такие вещи. Проблема другая.
Выполните шаг 2. На этом шаге мы технически не можем сказать, что если U1 отправляется в автономном режиме, он просто теряет соединение, скажем, в течение 2 секунд, возможно, из-за плохого интернета. Таким образом, U2 отправляет ему сообщение, но U1 не получает его, потому что интернет все еще для него (шаг 3). Шаг 4 необходим для обнаружения автономных пользователей, скажем, тайм-аут составляет 60 секунд. В конце концов через 10 секунд подключится интернет-соединение для U1, и он снова подключится к socket.io. Но сообщение из U2 теряется в пространстве, потому что на сервере U1 был отключен таймаутом.
В этом проблема, я не получаю 100% доставки.
Решение
- Соберите излучение (введите имя и данные) в {} пользователь, идентифицированный случайным emitID. Отправить emit
- Подтвердить испускание на стороне клиента (отправить emit обратно на сервер с emitID)
- Если подтверждено - удалить объект из {}, идентифицированный emitID
- Если пользователь повторно подключен - проверьте {} для этого пользователя и пропустите его, выполнив Шаг 1 для каждого объекта в {}
- При отключенном или/или подключенном флажке {} для пользователя при необходимости