익숙한
NodeJS, Socket.io
문제
Socket.io를 통해 앱에 연결된 두 명의 사용자 U1 및 U2 가 있다고 가정 해보십시오. 알고리즘은 다음과 같습니다.
- U1 이 인터넷 연결이 완전히 끊어짐 (예 : 인터넷 끄기)
- U2 는 U1에 메시지를 보냅니다 .
- U1 은 인터넷이 다운 되었기 때문에 아직 메시지를받지 못합니다.
- 서버 가 하트 비트 시간 초과로 U1 연결 끊김을 감지합니다.
- U1 이 socket.io에 다시 연결됩니다.
- U1 은 U2 로부터 메시지를받지 못합니다 . 4 단계에서 잃어버린 것 같습니다.
가능한 설명
왜 그런지 이해한다고 생각합니다.
- 4 단계에서 서버 는 소켓 인스턴스와 U1에 대한 메시지 큐 도 종료합니다.
- 또한 5 단계에서 U1 과 서버는 새 연결을 생성하므로 (재사용되지 않음) 메시지가 여전히 대기열에 있어도 이전 연결은 손실됩니다.
도움이 필요하다
이런 종류의 데이터 손실을 어떻게 방지 할 수 있습니까? 사람들이 앱에 영원히 매달리지 않기 때문에 저는 hearbeats를 사용해야합니다. 또한 새 버전의 앱을 배포 할 때 다운 타임이 전혀 발생하지 않기를 원하기 때문에 다시 연결할 수있는 가능성을 제공해야합니다.
추신 : 내가 "메시지"라고 부르는 것은 데이터베이스에 저장할 수있는 단순한 문자 메시지가 아니라 전달이 보장되어야하는 귀중한 시스템 메시지이거나 UI가 망가진 것입니다.
감사!
추가 1
이미 사용자 계정 시스템이 있습니다. 게다가 내 응용 프로그램은 이미 복잡합니다. 오프라인 / 온라인 상태를 추가해도 도움이되지 않습니다. 이미 이런 종류의 항목이 있기 때문입니다. 문제는 다릅니다.
2 단계를 확인하십시오.이 단계에서 U1이 오프라인 상태인지 여부 는 기술적으로 말할 수 없습니다 . 그는 인터넷 연결이 끊어졌을 뿐이고 인터넷 상태가 좋지 않아 2 초 동안 말할 수 있습니다. 그래서 U2는 그에게 메시지를 보내지 만 U1은 그에게 아직 인터넷이 다운되어 있기 때문에 메시지를받지 못합니다 (3 단계). 오프라인 사용자를 감지하려면 4 단계가 필요합니다. 예를 들어 시간 제한은 60 초입니다. 결국 10 초 후에 U1에 대한 인터넷 연결이 설정되고 socket.io에 다시 연결됩니다. 그러나 U1 서버에서 시간 초과로 연결이 끊어 졌기 때문에 U2의 메시지는 공간에서 손실됩니다.
그게 문제입니다. 100 % 배송하고 싶지 않습니다.
해결책
- 임의의 emitID로 식별되는 {} 사용자에서 방출 (방출 이름 및 데이터)을 수집하십시오. 방출 보내기
- 클라이언트 측에서 방출을 확인하십시오 (emitID를 사용하여 서버로 방출을 다시 보냅니다).
- 확인 된 경우-emitID로 식별 된 {}에서 오브젝트 삭제
- 사용자가 다시 연결 한 경우-이 사용자에 대해 {}을 확인하고 {}의 각 개체에 대해 1 단계를 실행하여 반복합니다.
- 연결이 끊어 지거나 연결되었을 때 필요한 경우 사용자를 위해 {} 플러시
// Server
const pendingEmits = {};
socket.on('reconnection', () => resendAllPendingLimits);
socket.on('confirm', (emitID) => { delete(pendingEmits[emitID]); });
// Client
socket.on('something', () => {
socket.emit('confirm', emitID);
});
솔루션 2 (종류)
2020 년 2 월 1 일에 추가되었습니다.
이것이 실제로 Websockets에 대한 솔루션은 아니지만 누군가가 여전히 편리하다고 생각할 수 있습니다. Websockets에서 SSE + Ajax로 마이그레이션했습니다. SSE를 사용하면 클라이언트에서 연결하여 지속적인 TCP 연결을 유지하고 서버에서 실시간으로 메시지를받을 수 있습니다. 클라이언트에서 서버로 메시지를 보내려면 Ajax를 사용하면됩니다. 대기 시간 및 오버 헤드와 같은 단점이 있지만 SSE는 TCP 연결이기 때문에 안정성을 보장합니다.
Express를 사용하기 때문에 SSE https://github.com/dpskvn/express-sse 에이 라이브러리를 사용 하지만 자신에게 맞는 라이브러리를 선택할 수 있습니다.
SSE는 IE 및 대부분의 Edge 버전에서 지원되지 않으므로 https://github.com/Yaffle/EventSource와 같은 polyfill이 필요합니다 .