서버 2대이상 띄웟을 때 채팅(웹소켓사용)

김성지·2022년 9월 9일
0

그냥공부

목록 보기
4/10

일단 현재 구현되어잇는거 정리..

채팅방에 입장하면
접속세션 생성+지난채팅기록 불러오기 api가 호출된다.

text채팅을 보내는 유저의 흐름을 살펴보면은

이게 호출된다.(채팅을 보낼라면 채팅방에 입장된 상태이고 이는 즉

chatRoomMap에 해당 유저의 세션이 담겨잇다는 뜻이다.
)

handleTextMessage 에는

1.chatService.createChat(chatMessage) 가 호출
2.sendRedisMessage 가 호출

chatService의 함수는
chat을 db에 저장하고
채팅방을 구독한(chatRoom db에 잇는)유저들에게 push 알람이 가도록 구현 되어잇다.(pushService 사용햇음)

2번(sendRedisMessage는)

event 패턴?을 적용햇는데

RedisMessageCreateEvent를 발생시켯다
eventListener을 보면은

redisSubscriber의 sendMessage 가 호출된다.

여기서 redisTemplate 의 메시지 기능을 사용한다.
convertAndSend가 호출된다.

문제는 여기까지 내가 구현한게 아니다..

채팅과 채팅룸의 데이터들을 db에 저장해놧는데
왜 redis를 쓰는지 부터 궁금증을 해결해보자

서버 2대 이상 띄워져잇어서

서로 같은 메시지를 주고받을라믄
redis가 메시지 브로커 역할을 해야한다..!이다

설정

설정정보다
1.채널 하나 파준다.

2.리스너 어댑터 등록

3.redis pub/sub 메시지를 처리하는 listener 설정

채팅방에 입장할 때는 ????

chatHandler 의

에서
메세지 브로커인 redis에게 알려주면 된다.

근데 잘 모르겟음...
redisTemplate.converAndSend가 (pub 상황)
모든메시지에서 거쳐가는대

redis Pub/Sub

이것부터 알아야 할듯
redis는 pub/sub messaging 패러다임 제공한다.
publisher는 'channel'이라는 곳에 메시지를 보내고
subscriber는 하나 이상의 'cahneel'로 부터 메시지를 수신하는 형태이다.

'channel'이라는 매개체로 publisher와 subscriber는 서로 decouple 되어 잇어서
보다 유연한 확장성과 동적 네트워크 topology를 제공한다.

또한 Redis의 Pub/Sub는 pattern 매칭을 제공하는데 만약에 subscriber가 news.* 패턴의 모든 메시지에 관심이 있다면 news.sports, news.stock과 같은 패턴의 channel에 보내진 메시지를 모두 수신하게 된다.

메시지 발송

RedisTemplate 의 convertAndSend(channel,message) 를 이용하여 설정된
'channel'로 메시지를 보내게 된다. (없는 채널이라면 아마 새로 생성되는 듯 한다. 이것도 직접해보거나 찾아봐야 겠다.)

메시지 수신

수신할라면

MessageListenerAdapter 설정해줘야한다.

다음과 같이 작동한대요

  1. MessageListenContainer 로 부터 메시지를 받는다.
    2.등록된 커스텀 리스너 유형이 org.springframework.data.redis.connection.MessageListener인 경우에는 수신된 메시지를 등록된 리스너에게 전달.
    3.만약에 등록된 리스너가 MessageLinstener 유형이 아닌 경우에는 reflection을 이용하여 등록된 리스너의 메소드의 인자를 확인 후 해당 메소드에 메시지와 channel 또는 pattern을 넘겨 준다.
  2. 최정적으로 등록된 리스너에서 수신된 메시지로 비즈니스 로직에 맞게 처리하면 된다.(비즈니스 로직이란 커스텀 클래스를 말한다고한다.)

RedisMessageListenerContainer

RedisMessageListenerContainer는 Redis의 channel로 부터 메시지를 수신받아 해당 MessageListenerAdapter에 dispatch 하게 된다고 한다.

동작방식은
1.TaskExecutor를 이용하여 등록된 리스너에게 비동기적으로 메세지 dispatch
2.하나의 connection과 하나의 thread를 등록된 여러 리스너가 공유
3.RedisConnection과 같은 resource 생성 및 release

exceptino 발생하면 jedis exception 에서 sprnig exception으로 변환된다고 한다..!

흐름

1.서버 2대 이상 띄워져잇음
2.서버는 한대의 래디스랑 연결
3.메시지 pub 하면 2대가 listen 하고 잇으니간
session을 공유하고 잇지 않아도 되는 문제는 사라졋다.

connection 이 종료될 때 처리

  1. session 삭제
    끝 아닌가 ?

왜 disconnection message를 또 날리는가 햇더니...

클라이언트 쪽에서 roomId의 세션리스트들을 알고잇는 상태라고 한다...
메시지 읽음처리 때문에 그랫던거 같다 ㅠㅠㅠㅠㅠ

정리하면

그냥 메시지 브로커 하나 둔거다
2대 이상의 서버는 브로커를 무조건 거쳐가니깐
채팅방에서
하나의 서버가 다른 서버의 SESSION을 알필요가 없다
브로커가 pub sub 하는것만 받아먹으면 대니깐..
세션관리를 레디스에게 위임했다

사용자료출처

https://daddyprogrammer.org/post/3688/redis-spring-data-redis-publish-subscribe/

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=willygwu2003&logNo=130172636498

0개의 댓글

관련 채용 정보