Skip to content

DirectMessage Service

Masuri edited this page Sep 28, 2022 · 10 revisions

Direct Message

Overview

빠른 응답성을 요구하는 실시간 채팅 서비스인 Direct Message 서비스에 대해 설명합니다. 실시간 소켓 통신을 위해 SignalR을 사용했고 DB 저장 시간을 줄이고 빠르게 사용자에게 응답하기 위해 빠른 메모리 DBRedis를 사용했습니다. 사용자가 전달해 온 데이터가 정합성 검사를 통과하면 1차적으로 Redis에 저장하고 백그라운드 서비스에서 DB로 영구저장 됩니다.


Alt Text

Nuget Packages

NAME REASON FOR USE
SignalR 소켓을 사용한 실시간 통신을 하기 위해서
Redis 실시간 통신의 응답성을 향상시켜 주기 위해서
Entity Framework CORE ORM

Description

  1. Client가 로그인을 성공하고 서비스를 이용할 준비를 마쳤다.

  2. 서버는 사용자의 ID와 Connection ID를 {key:value} 형태로 Connection Manager에 저장해둔다.1

  3. Client에서 chat창을 연다.

  4. HTTP 통신으로 기존에 했던 대화를 가져온다.

  5. Client에서 Direct Message를 다른 Client에게 보낸다.

  6. 소켓을 통해 메시지 정보가 DirectMessageHub에 보내지면 메시지를 파씽하고 비동기적으로 Redis에 저장한다.2 Redis에서 저장하는 동시에 2번에서 저장한 Connection Manager를 이용해 받는 사람의 Connection ID를 가져와 상대 Client에게 메시지를 보낸다.

  7. Redis에 저장된 데이터는 멀티쓰레드 세이프한 Channel<T>을 통해 DB 삽입 쓰레드와 pub/sub구조로 연결된다. Channel<T>에 입력되는 데이터는 비동기 스트림 방식으로 DB 삽입 쓰레드에서 데이터를 폴링해 DB에 영구 저장된다.


How to save data to the db

CacheService에서 빠른 응답성을 갖으면서 데이터 저장을 하기 위해 Redis에 데이터를 전송하고 데이터 저장 유무와 관련없이 바로 리턴한다. 이렇게 하면 빠른 응답성을 요구하는 채팅 서비스에서 클라이언트는 즉각적인 응답을 받을 수 있다. 동시에 안전한 멀티쓰레드 pub/sub이 가능한 Channel<T> 자료구조를 이용해 비동기 스트림 방식으로 데이터를 폴링해 DB에 영구 저장한다.

Alt Text

Description

  1. Client에서 Direct Message 데이터가 들어온다

  2. 비동기적으로 Channel<T>에 데이터를 저장하고 저장 유무에 상관없이 클라이언트에게 리턴한다.

  3. 비동기 스트림 방식으로 Channel<T>를 폴링하던 DB 삽입 쓰레드는 Channel<T>에 데이터가 입력 되는 즉시 그것으로부터 데이터를 가져와 DB 저장을 시도한다.



Footnote

1: SignalR은 각 Client마다 자신의 Connection Id를 갖고 Application은 Client를 User의 DB Primarykey로 구분하기 때문에 둘의 연결관계를 만들어 줘야 SignalR입장에서는 들어온 메시지에 들어있는 Id를 이용해 올바른 Client에게 응답을 전달할 수 있다.

2: 응답성이 중요한 소켓통신에서 DB에 저장되는 지연시간을 최소화 하기 위해 빠른 Redis에 저장 후 다른 쓰레드로 DB에 영구 저장한다.

Clone this wiki locally