확실히 실시간 채팅을 구현하려 하면서 많은 문제점들이
발견되었습니다.
첫번째로
이렇게 리액트 쪽, 프론트 서버쪽에서 eventSource를 통해 백엔드에 요청을 하고 난 뒤
이렇게 close를 넣어주지 않으니 새로 고침을 하지 않는 이상 (리액트 라우터를 통해 페이지 이동)
닫히지 않는 SSE통신은 6개를
초과하며 채팅방이 열리지 않는 현상을 발견했습니다. 그래서
Use effect와 history를
통해 페이지를 벗어날 경우 close를 만들어 주어 일단 문제를 해결했습니다.
따로 close 처리를 해주지 않으면 지속됩니다. (아니면 새로 고침으로 초기화가 되긴 한다.)
한가지 문제가 더 있는데 일단
서버가 메모리 누수인지는 잘 모르겠지만 한번 죽어버리면 시간이 지나도 복구하지 못한다는 점입니다.
이렇게 100번이상의 밸류가 들어가면 프론트 서버에서 close를 넣어도
백엔드 쪽에서는 확실히 끊기지 않았던 것인지는 모르겠지만
(물론 한브라우저에서 6번이상
시도해도 열리긴 한다.)
죽어버려 요청이 안되는 현상을 계속 받고있습니다.
물론 방법도 많습니다. API GATEWAY 의 로드 밸런싱을 이용해
한번에 5개 이상의 어플리케이션을 작동시켜
대략 어플리케이션 1개당 50명의
요청을 견딜 수 있다고치면 250명정도의 실시간 채팅 요청을 받아낼수는 있겠지만…
사실 제 생각에는 50명의 요청도 버거울 꺼 같습니다. 문제점 해결이 필요했습니다.
일단 이 block코드를 먼저 해결 하는 것이 우선이였습니다.
Non-block이 강점인 현재 채팅 어플리케이션에
저렇게 block사용한다면 안 쓰는 거나 마찬가지라는 생각이 들어
따로 코드를 찾아본 결과
switchIfEmpty 사용법을 찾아냈고
이렇게 적용까지 해봤습니다.
추가내용 (23.03.10)
원인은 MongoDBClient였습니다.
처음에는 Schedulers의 관리 문제 인줄 알고 집중적으로 찾았습니다. 하지만 그게 문제가 아니 였습니다.
MongoDBClient가 연결을 요청할 때 하나의 connection을 여는데 여기서 중요한게 저는 따로 Client 설정을
두지 않아 기본값인
maxConnectionListTime : 즉 라이프 사이클 최대 시간과
maxConnectionIdelTime : 연결 유효시간 (연결이 몇 초 동안 부재일 때 연결을 해제할지 라는뜻) 설정을
따로 해두지 않아서 (Default는 0, -1 즉 연결 시 따로 끊지 않으면 계속 누적된다) 생기는 문제였습니다.
아무리 스케줄러를 dispose해서 끊어 내도 커넥션이 끊기지않으니 pool이 다 차서 발생한 문제였습니다.
이렇게 설정하면서 한동안 막혔던 connection pool 멈춤
현상은 해결할 수 있었습니다.
이상입니다.
(해당 트러블슈팅을 하면서 추가적으로 공부 해야 할 것)
Spring cache (캐시)
스케줄러 관리에 큰 도움이 됨 :
https://wiki.terzeron.com/Programming/Java/Reactor_Flux%EC%9D%98_publishOn_subscribeOn%EC%9D%84_%EC%9D%B4%EC%9A%A9%ED%95%9C_%EC%8A%A4%EC%BC%80%EC%A5%B4%EB%A7%81