[BE / 로비서버] 유저 기존 세션 유지한 채 다른 세션으로 재입장 시 기존 세션 끊기
Closed this issue · 9 comments
Tae-Hyeon commented
방법 찾기
- 현재 구조에서 가능한 방법을 찾지 못하겠다.
- 로비 서버가 여러개라 기존 세션과 다른 세션이 각각 다른 서버에 연결될 수 있다.
- 이게 가장 문제
- 방법 1
- 유저가 입장할 때, 유저의 세션 id를 유저id-세션id 로 Redis에 저장한다.
- 유저가 입장할 때, Redis의 정보를 가져와 유저-세션이 존재한다면 세션 close를 한다.
- publishing을 통해 유저 입장 메세지에 세션 id를 같이 날린다.
- 다른 서버에서 세션 id를 통해 방 정보를 찾고 해당 방의 유저 정보를 삭제하고 세션을 종료한다.
- 문제 발생
- 같은 방에 재입장 했을 경우 문제가 발생한다.
- publishing한 메세지를 늦게 받을 경우, 방에 입장했고, 새로운 세션이 생겼지만, 다른 유저는 나갔다는 메세지를 늦게 받게된다.
- 이 때문에, 결론적으로 유저가 나가버리는 문제가 발생한다.
Tae-Hyeon commented
세션-방 관계 컬렉션이 있으니까, 이를 가지고 입장하는 방과, 세션에 해당하는 방이 같으면 나가기 메세지를 보내지 않도록 할까?
- 이렇게 하면 중복 입장이 될수도 있다. --> 입장 메세지도 전파하지 않으면 되나?
- 서버가 같다면 처리가 되지만, 다른 서버들에서는 중복 입장이 될 것 같다.
Tae-Hyeon commented
레디스에 세션id + 방 id를 모두 저장하면 입장 시 입장 방 id와 레디스 정보를 비교하여 메세지 전송 여부를 분기 처리하면?
- 다른 방에 있으면 그대로 보내서 나가도록 처리하면 되고, 같은 방이면 사실상 세션 정보만 바뀌고, 나가진 않는다.
- 대신 다른 서버에서 기존 세션에 해당하는 정보를 삭제하도록 새로운 메세지가 필요?
- 다른 방에 입장 시 - 입장 메세지의 기존 세션id를 통해 나가기 처리
- 같은 방에 입장 시 - 세션 정보만 삭제하고, closeConnection 메소드가 아닌 session close
- 삭제할 것
- session_room
- user_session Map (같은 서버일 경우 갱신되기 때문에 필요한가?)
- 서버가 다를 경우를 어떻게 판단해야하나
- room 내의 sessions Map (이것도 마찬가지로 갱신되기 때문에 필요한가?)
- 서버가 다를 경우를 어떻게 판단해야하나
- userData Map
Tae-Hyeon commented
STOMP의 구조를 생각하면 해결할 수 있지 않을까?
- 유저마다 특정 방에 대해 subscribe하게된다.
- RabbitMQ의 topic을 잘 활용하면 될 것 같다.
- 지금까지는 fanout방식으로 사용하고 있었다.
- 로드밸런싱을 샤딩처럼 할 수 있을까? --> 같은 서버에 유저를 몰아두면 편하지 않을까?
- 유저 수가 많은데 이에 따라 구역을 나눌 수 있을까?
Tae-Hyeon commented
- STOMP는 동적으로 queue를 생성한다.
- 이것을 따로 구현하기에는 어려움이 있다.
Tae-Hyeon commented
- 좀 비효율적이지만 필터링을 잘 거치면 임시 해결은 될 것 같다.
- 새 브랜치를 파서 수정을 해봐야겠다.
Tae-Hyeon commented
현재 생각하는 로직
Session Storage 이용 - Redis
- 입장 시 Redis에 userId-sessionId,roomId를 저장해 놓는다
- 유저가 입장하면 userId를 키로 Redis에서 값을 가져온다.
- 이미 유저가 세션이 등록되어 있다면, 세션 클로징 메세지를 발행한다.
- 세션 클로징 메세지 내용
- postRoomId|USER_MULTI_ENTER|data
- data
- preSessionId,, postSessionId, preRoomId
- 세션 클로징 단계 (preSessionId가 있다면 아래 로직 실행)
- userId-sessionId
- preSessionId value가 있다면 삭제
- sessionId-userDetails
- preSessionId key가 있다면 삭제
- sessionId-roomId
- preSessionId key가 있다면 삭제
- roomId-room
- sessionId-session
- preSessionId가 있다면 session 클로즈 & 삭제
- userId-userDto
- sessionId-session에 postSessionId가 Key로 없으면 삭제
- sessionId-session
- userId-sessionId
Tae-Hyeon commented
같은 방에 입장은 막고 다른 방의 입장은 커넥션을 끊는다?
Tae-Hyeon commented
생각해보니 다른 방에 중복 입장은 크게 상관이 없을지도?
서버에서 유저 당 하나의 세션 정보를 유지한다.
- 이것도 기존 세션을 끊는 용도로 사용할 것이었기 때문에, 없애면 그만?
- 실제로 코드를 체크해 봤을 때, 끊는 용도가 아니면 사용을 하지 않는다.
- 세션 id를 키로 갖고있는 컬렉션이 있기도 하고, 레디스에 상태를 저장한다면, 굳이 필요 없는 컬렉션이다.
Tae-Hyeon commented
그래도 입장을 막는 것은 아니라고 생각해서 다른 방에 접근할 때는 허용하되, 같은 방에 중복 입장할 경우에 기존 세션을 끊는 것으로 해결했다.