Websockets와 클라이언트 서버 커뮤니케이션에서의 역할에 대한 깊은 다이빙

실시간 커뮤니케이션은 라이브 챗봇, 데이터 스트림 또는 인스턴트 메시징 등 어디에서나 있습니다. Websockets는 이것의 강력한 가능성이지만 언제 사용해야합니까? 그들은 어떻게 일하고, 기존의 HTTP 요청과 어떻게 다른가요?
이 기사는 최근 시스템 설계 인터뷰 (실시간 메시징 앱 설계”에서 영감을 얻었습니다. 여기서 몇 가지 개념을 우연히 발견했습니다. 이제 더 깊이 파고 들었으므로 배운 것을 공유하여 같은 실수를 피할 수 있습니다.
이 기사에서는 Websockets가 클라이언트 서버 커뮤니케이션의 더 큰 그림에 어떻게 적합한 지 탐색합니다. 우리는 그들이 잘하는 일, 그들이 부족한 곳, 그리고 실시간 메시징 앱을 설계하는 방법에 대해 논의 할 것입니다.
클라이언트 서버 커뮤니케이션
핵심적으로 클라이언트-서버 커뮤니케이션은 클라이언트와 서버의 두 엔티티 간의 데이터 교환입니다.
클라이언트는 데이터를 요청하고 서버는 이러한 요청을 처리하고 응답을 반환합니다. 이러한 역할은 배타적이지 않습니다. 서비스는 상황에 따라 클라이언트와 서버 모두 동시에 작용할 수 있습니다.
WebSockets의 세부 사항을 다이빙하기 전에 한 걸음 물러서 클라이언트 서버 커뮤니케이션 방법의 더 큰 그림을 살펴 보겠습니다.
1. 짧은 투표
짧은 투표는 가장 간단하고 가장 친숙한 접근법입니다.
클라이언트는 새로운 데이터를 확인하기 위해 정기 간격 (예 : 몇 초마다)으로 HTTP 요청을 서버에 반복적으로 보냅니다. 각 요청은 독립적이고 1 차선 (클라이언트 → 서버)입니다.
이 방법은 설정하기 쉽지만 서버에 새로운 데이터가 거의없는 경우 리소스를 낭비 할 수 있습니다. 가끔 폴링이 충분한 시간에 민감한 응용 프로그램에 사용하십시오.
2. 긴 폴링
긴 폴링은 짧은 설문 조사에 비해 개선으로 불필요한 요청의 수를 줄이기 위해 고안되었습니다. 서버가 클라이언트 요청에 즉시 응답하는 대신 서버 연결을 계속 열어줍니다 새로운 데이터를 사용할 수있을 때까지. 서버에 데이터가 있으면 응답을 보내고 클라이언트는 즉시 새 연결을 설정합니다.
긴 폴링도 있습니다 무국적 그리고 1 차선 (클라이언트 → 서버).
일반적인 예는 클라이언트가 일치 또는 예약 업데이트를 기다리는 Ride -Hailing 앱입니다.
3. Webhooks
Webhooks는 서버를 개시 자로 만들어 스크립트를 뒤집습니다. 서버가 전송됩니다 HTTP 게시물 특정 이벤트가 발생할 때마다 클라이언트 정의 엔드 포인트에 대한 요청.
각 요청은 다음과 같습니다 독립적인 지속적인 연결에 의존하지 않습니다. Webhooks도 있습니다 1 차선 (서버 대 클라이언트).
WebHooks는 특히 타사 서비스와 통합 할 때 비동기 알림에 널리 사용됩니다. 예를 들어, 결제 시스템은 WebHooks를 사용하여 거래 상태가 변경 될 때 클라이언트에 알립니다.
4. 서버 중앙 이벤트 (SSE)
SSE는 a입니다 기본 HTTP 기반 이벤트 스트리밍 프로토콜 이를 통해 서버는 실시간 업데이트를 단일에 걸쳐 클라이언트에게 푸시 할 수 있습니다. 지속적인 연결.
SSE는 EventSource
API, 최신 웹 애플리케이션에서 구현하기 간단합니다. 그것은 1 차선 (서버로 클라이언트) 및 클라이언트가 업데이트를 수신 해야하는 상황에 이상적입니다.
SSE는 트레이딩 플랫폼이나 라이브 스포츠 업데이트와 같은 응용 프로그램에 적합하며 서버는 주가 또는 점수와 같은 데이터를 실시간으로 푸시합니다. 클라이언트는 이러한 시나리오에서 데이터를 서버로 다시 보낼 필요가 없습니다.
그러나 양방향 커뮤니케이션은 어떻습니까?
위의 모든 방법은 1 방향 흐름에 중점을 둡니다. 진정한 양방향 실시간 교환의 경우 다른 접근 방식이 필요합니다. 그것이 Websockets가 빛나는 곳입니다.
다이빙합시다.
Websockets는 어떻게 작동합니까?
Websockets가 활성화됩니다 실시간, 양방향 통신채팅 앱, 라이브 알림 및 온라인 게임과 같은 응용 프로그램에 적합합니다. 기존의 HTTP 요청-응답 모델과 달리 WebSockets는 a를 만듭니다 지속성 있는 클라이언트와 서버가 요청을 기다리지 않고 독립적으로 메시지를 보낼 수있는 연결.
연결은 일반적인 HTTP 요청으로 시작되며 악수를 통해 WebSocket 연결로 업그레이드됩니다.
일단 설립되면 단일 TCP 연결을 사용하여 HTTP (80 및 443)와 동일한 포트에서 작동합니다. Websockets를 통해 전송 된 메시지는 작고 가벼워서 낮은 비율의 높은 상호 작용 사용 사례에 효율적입니다.
WebSocket Connections 특정 URI 형식을 따릅니다. ws://
정기적 인 연결 및 wss://
안전하고 암호화 된 연결.
악수는 무엇입니까?
악수는 과정입니다 연결 초기화 두 시스템 사이. WebSockets의 경우 클라이언트의 HTTP GET 요청으로 시작하여 프로토콜 업그레이드를 요청합니다. 이를 통해 지속적인 WebSocket 연결로 전환하기 전에 HTTP 인프라와의 호환성을 보장합니다.
- 클라이언트는 다음과 같은 헤더와 함께 요청을 보냅니다.
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin:
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Upgrade
– 프로토콜을 전환하라는 요청을 표시합니다Sec-WebSocket-Key
– 무작위로 생성 된 Base64 인코딩 된 문자열 핸드 셰이크 확인에 사용됩니다.Sec-WebSocket-Protocol
(선택 사항) – 클라이언트가 지원하는 서브 프로토콜을 나열하여 서버가 선택할 수 있습니다.
2. 서버는 Resquest에 응답합니다
서버가 WebSockets를 지원하고 업그레이드에 동의하면 101 스위칭 프로토콜 상태. 예제 헤더 :
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Accept
– Base64 클라이언트의 해시를 인코딩했습니다Sec-WebSocket-Key
그리고 안내. 이를 통해 악수가 안전하고 유효합니다.
3. 핸드 셰이크 검증
함께 101 Switching Protocols
응답, WebSocket 연결이 성공적으로 설정되었으며 클라이언트와 서버 모두 실시간으로 메시지 교환을 시작할 수 있습니다.
이 연결은 어느 당사자가 명시 적으로 닫을 때까지 열려 있습니다.
다른 코드가 아닌 경우 101
반환되면 클라이언트는 연결을 종료해야하며 WebSocket 핸드 셰이크가 실패합니다.
다음은 요약입니다.

WebSocket 사용 사례
우리는 Websockets가 실시간, 양방향 통신을 가능하게하는 방법에 대해 이야기했지만 여전히 추상적 인 용어입니다. 몇 가지 실제 사례를 꺼 봅시다.
WebSockets는 Excalidraw, Telegram, WhatsApp, Google Docs, Google지도 및 YouTube 또는 Tiktok 라이브 스트림과 같은 실시간 협업 도구 및 채팅 응용 프로그램에 널리 사용됩니다.
트레이드 오프
1. 연결이 종료되면 폴백 전략이 있습니다
네트워크 문제, 서버 충돌 또는 기타 고장으로 인해 연결이 종료되면 웹 소켓이 자동으로 복구되지 않습니다. 클라이언트는 단절을 명시 적으로 감지하고 연결을 다시 설정하려고 시도해야합니다.
긴 폴링 WebSocket 연결이 재건하려고하는 동안 종종 백업으로 사용됩니다.
2. 오디오 및 비디오 데이터 스트리밍에 최적화되지 않았습니다
WebSocket 메시지는 전송을 위해 설계되었습니다 작고 구조화 된 메시지. 큰 미디어 데이터를 스트리밍하기 위해 WebRTC와 같은 기술이 이러한 시나리오에 더 적합합니다.
3. 웨켓 셋은 상태가 적합하므로 수평 스케일링은 사소하지 않습니다.
웨이브 톱니는입니다 상태가 있습니다즉, 서버는 모든 클라이언트에 대한 활성 연결을 유지해야합니다. 이로 인해 Server가 지속적인 상태를 유지하지 않고 클라이언트 요청을 처리 할 수있는 Sationeless HTTP에 비해 수평 스케일링이 더욱 복잡해집니다.
이를 위해서는 추가 펍/하위 메커니즘 계층이 필요합니다.
실시간 메시징 앱을 설계하십시오
이제 이것이 시스템 설계에 어떻게 적용되는지 봅시다. 간단한 (고정 불가능한) 솔루션과 수평 스케일 솔루션을 모두 다루었습니다.

비정치 단일 서버 앱 : 두 사용자가 실시간으로 채팅하는 방법은 무엇입니까?
- 모든 사용자는 WebSocket을 통해 하나의 서버로 연결합니다. 서버는 메모리 내 매핑을 보유합니다
userID : WebSocket conn 1
- user1은 WebSocket 연결을 통해 서버에 메시지를 보냅니다.
- 서버는 메시지를 MessagedB에 씁니다 (Persistence First).
- 그런 다음 서버가 조회합니다
user2 : WebSocket conn 2
메모리 맵에 있습니다. user2가 온라인 인 경우 메시지를 실시간으로 전달합니다. - user2가 오프라인 인 경우 서버는 inboxdb (배달되지 않은 메시지 저장)에 기록합니다. user2가 온라인으로 돌아 오면 서버는 inboxdb에서 모든 오프라인 메시지를 가져옵니다.
수평 스케일링 시스템 : 두 사용자가 어떻게 실시간으로 채팅합니까?
단일 서버는 너무 많은 동시 웹 소켓 만 처리 할 수 있습니다. 더 많은 사용자에게 서비스를 제공하려면 WebSocket 연결을 가로로 확장해야합니다.
주요 과제 : User1이 Server1에 연결되어 있지만 User2가 Server2에 연결되어 있으면 시스템이 메시지를 어디로 보낼 위치를 어떻게 알 수 있습니까?
Redis는 맵핑하는 글로벌 데이터 스토어로 사용할 수 있습니다. userID : serverID
활성 WebSocket 세션의 경우. 사용자가 연결 (온라인으로 이동) 또는 연결을 끊을 때 각 서버가 REDIS를 업데이트합니다 (오프라인으로 이동).
예를 들어:
-
user1은 Server1에 연결합니다. Server1의 메모리 맵 :
user1 : WebSocket connection
Server1은 또한 redis에 글을 씁니다.user1 : server1
-
user2는 Server2에 연결합니다. 메모리 맵에있는 Server2 :
user2 : WebSocket connection
Server2는 또한 redis에 글을 씁니다.user2 : server2
끝에서 끝에서 채팅 흐름 : user1은 user2에 메시지를 보냅니다.
- user1은 Server1의 WebSocket을 통해 메시지를 보냅니다.
- Server1은 메시지를 채팅 서비스로 전달합니다.
- 채팅 서비스는 먼저 지속성을 위해 Messagedb에 메시지를 씁니다.
- 그런 다음 채팅 서비스는 redis를 확인하여 user2의 온라인/오프라인 상태를 얻습니다.
- user2가 온라인 상태 인 경우채팅 서비스는 메시지를 메시지 브로커에 게시하여 “User2 : Server2″로 태그를 붙입니다.
- 그런 다음 중개인은 메시지를 Server2로 라우팅합니다.
- Server2는 메모리 매핑의 로컬이며 user2의 WebSocket 연결을 찾아 해당 WebSocket을 통해 메시지를 실시간으로 푸시합니다.
- user2가 오프라인 인 경우 (Redis의 항목 없음)채팅 서비스는 inboxdb에 메시지를 씁니다. user2가 온라인으로 돌아 오면 채팅 서비스가 전달되지 않은 모든 메시지를 가져옵니다.
- 새 WebSocket 연결이 열리거나 닫힐 때마다 서버가 Redis를 업데이트합니다.
- 사용자가 처음 앱을로드하거나 채팅을 열면 채팅 서비스는 MessagedB에서 과거 메시지 (지난 10 일 동안)를 가져옵니다. 캐시 레이어는 반복 된 DB 쿼리를 줄일 수 있습니다.
몇 가지 중요한 설계 고려 사항 :
-
지속성 먼저 모든 메시지는 배달되기 전에 DB로 이동합니다. WebSocket 로의 푸시가 실패하면 DB에서 메시지가 여전히 안전합니다.
-
레 디스 백화점 오직 활동적인 오버 헤드를 최소화하기위한 연결. 단일 고장 지점을 방지하기 위해 복제본을 추가 할 수 있습니다.
- 받은 편지함 DB는 오프라인 케이스를 깨끗하게 처리하는 데 도움이됩니다.
-
채팅 서비스 추상화 WebSocket 서버는 실시간 연결 및 라우팅을 처리합니다. 채팅 서비스 계층은 HTTP 요청을 처리하고 모든 DB가 쓰여집니다. 이러한 우려의 분리는 각 조각을 쉽게 확장하거나 진화시킬 수있게합니다.
-
메시지 전달 순서 보장 일반적인 “실시간 푸시”워크 플로는 네트워크 변형을 가질 수있어 메시지가 주문되지 않습니다. 많은 메시지 중개인도 있습니다 보장하지 마십시오 엄격한 주문. 이를 처리하기 위해 각 메시지에는 생성시 타임 스탬프가 할당됩니다. 메시지가 순서대로 도착하더라도 클라이언트는 타임 스탬프를 기반으로 재정렬 할 수 있습니다.
-
로드 밸런서 스티커 WebSocket 연결을위한 L4로드 밸런서 (TCP). 정기적 인 요청 (CRUD, 로그인 등)에 대한 L7로드 밸런서 (HTTP).
마무리
그게 다야! 우리가 탐험 할 수있는 훨씬 더 많은 것이 있지만, 이것이 당신에게 확실한 출발점을 주셨으면합니다. 아래 의견에 질문을 삭제하십시오.
나는 Python, 소프트웨어 개발 및 내가 구축 한 프로젝트에 대해 정기적으로 글을 쓰므로 놓치지 않도록 계속해서 작성하십시오. 다음 기사에서 뵙겠습니다.
출처 참조
Post Comment