~/csslab.dev/notes $ ls

// note

수평 확장 WebSocket — 어느 인스턴스에 붙었는지 찾아 보내기

  • LLM 어시스턴트 서비스의 실시간 통신 계층

증상

  • WS 서버를 여러 대로 늘렸더니 작업 완료 알림이 사용자에게 도달하지 않고 유실됨
  • 서버 한 대일 때는 멀쩡했음

원인

  • 사용자 소켓은 여러 인스턴스 중 한 대에만 붙음
  • 알림을 만들어내는 처리는 부하 분산으로 어디서 돌지 모름 — 소켓이 인스턴스 1에 있는데 이벤트는 인스턴스 2에서 발생
  • 인스턴스 2는 그 소켓 객체를 갖고 있지 않으니 그냥 보내면 사라짐

조치

  • 연결이 어디에 붙었는지를 Redis에 기록 — 연결 → 인스턴스 매핑과 인스턴스 → 연결 목록 두 방향. 인스턴스마다 고유 id를 갖고 그 id로 자기 채널 이름을 만듦
  • 보낼 때 먼저 조회 — 내가 들고 있으면 바로 push, 아니면 상대 인스턴스 채널로 Pub/Sub 발행. 각 인스턴스는 자기 채널을 구독하다가 받으면 자기 소켓으로 내보냄
  • 보내는 쪽은 상대가 어디 있는지·서버가 몇 대인지 몰라도 됨
  • 정리 경로를 두 갈래로 — 정상 종료 시 매핑 삭제, 비정상 종료는 만료 시간에 맡김. 정상 경로만 믿으면 죽은 항목이 쌓이고, 만료만 믿으면 해제 후에도 남음

결과

  • 인스턴스를 늘려도 알림이 사용자의 실제 연결로 도달
  • 이벤트를 만드는 쪽이 소켓 위치를 알 필요가 없어짐

클라이언트 쪽에서 연결이 끊겼을 때 되살리는 문제 → 소켓 재연결