• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

소켓 서버의 수평적 확장 및 무중단 배포에 대해 질문드립니다!

24.04.04 18:13 작성 조회수 221

3

안녕하세요, 소켓 서버의 수평적 확장 및 무중단 배포에 대해 궁금한 점이 있어 질문드립니다. 🙂

state를 갖고 있는 소켓 서버의 특징으로 인해 수평적 확장이 쉽지 않을 것 같은데요, 하지만 scale up 자체는 한계가 있기 때문에 강의의 주제처럼 대용량의 소켓 서버를 만드려면 결국 여러 대의 소켓 서버를 활용해야 할 것으로 예상됩니다.

그렇다면 실무에서는 어떤 방식으로 소켓 서버를 scale out 하게 되는지 궁금합니다! go 혹은 node 서버 진영에서 사용되는 프레임워크나 방식이 있을까요?

 

또한, 강의에서 보여주신 소켓 서버 예시는 connection를 메모리에 들고 있기 때문에 서버를 종료하게 될 경우, 기존의 소켓 채널이 모두 닫히게 될 것 같아요! 혹시 소켓 서버의 무중단 배포를 하고 싶다면, 어떤 식으로 작업을 구성하게 되는지도 궁금합니다.

감사합니다! 🙏

답변 2

·

답변을 작성해보세요.

3

안녕하세요 답변이 늦어서 죄송합니다. 일단 강의 목적이 굉장히 간단한 채팅서버를 구현하는것을 목표로 하였기 떄문에 이런 난이도가 있는 질문이 들어올지는 몰랐네요. 😊😊

글이 조금 길어질수도 있기 떄문에 답변을 나눠서 설명을 드려보도록 할게요.
- 좀 더 전문적인 지식에 용어가 첨부가 될 수도 있는데, 다른분들도 보시면 좋을만한 질문이라고 생각을하여 최대한 제가 평소에 쓰는 언어로 작성을 해보겠습니다. 제가 평소에 굉장히 쉽게 말하는것을 좋아해서.. ㅎ

일단 무중단 서비스를 구성하기 위해서는 가장 중요한 부분은 인프라입니다.

당연하게도 모두가 사용하시는 로드밸런서로 구동을 시켜야 무중단 서비스가 기본적으로 완성이 됩니다.

이떄 NatIP를 맨 앞상단에 두고, 해당 Nat이 들어오는 모든 요청을 하부에 있는 다른 IP를 전송을 함으로써 기본적으로 구성이 됩니다.
- 로드밸런싱 규칙은 상황에 따라 다르게 적용이 되겠죠

  • https://habitus92.tistory.com/22 이런글을 참고해보셔도 좋을꺼같네요.


    아키텍처에 대해서는 딱히 정답은 없지만, 거의 기본적으로 이러한 구조를 가지고 있을겁니다.

그럼 서버를 한번 살펴보도록 할게요.

일단 강의에서는 서버 메모리를 통해서 작업을 진행을 하였습니다. 최대한 간단하게 강의를 구성학싶었습니다.

하지만 실제 실무에서는 당연하게도 DB가 적용이 됩니다.

해당 강의에서 관리하는 거의 모든 메모리값들은 DB로써 관리가 되게 됩니다.

게임서버를 구축을 한다고 해도, 간단한 인벤토리를 열어보는 요청 자체도 HTTP로 구성이 되며, DB에 대한 커넥션이 반드시 일어나야하기 떄문에,

이러한 서버 메모리성 데이터가 DB로 관리가 된다는것은 크게 놀랍지 않은 상황이라고 생각을 합니다.

좀 더 서버에 대한 이야기를 해보도록 할게요.

채팅서버는 좀 더 복합적이고 굉장히 어려운 서버입니다. Ws라는 특성상 말씀하신거처럼 커넥션이 유지되어야 하기 떄문이죠

 

이떄 사용해야 하는데 일반적인 Pub/Sub 모델링이라고 하는 방식이 사용이 됩니다.

이렇게 되면, 다른 인스턴스 간의 통신이 지원이 되기 떄문에, 구독 패턴을 사용해서 좀 더 데이터 통신에 대한 보장을 할 수 있겠죠

 

그래서 일반적으로 소켓 서버를 구축하게 되면, Redis or kafkaf 같은 브로드캐스트를 진행 할 수 있는 추가적인 툴이 필요합니다.

 

또한 부가적으로 설명을 드리면 웹소켓에 대해서 라운드로빈 방식은 사용을 잘 하지 않는것으로 알고 있습니다. 부하적인 요소로 인해서

제가 데브옵을 안한지 너무나도 오래되어서 대신 사용하는 방식은 기억이 나지 않네요 ㅠㅠ 죄송합니다.

 

그리고 실질적으로 Client측에서 곧바로 Socket에 붙는 경우는 없습니다. 일단 하나의 게이트웨이 서버를 구축해서, 해당 서버에 일반적인 HTTP를 요청해, 사용가능한 socket URL을 받은 후에 연결을 하지 바로 연결을 진행하지는 않습니다.

바로 연결을 진행하면 당연하게도 장애가 쉽게 발생 할 수있겠죠

 

이 상황을 정리하면 다음과 같을꺼 같아요

a,b,c 라는 세개의 서버가 구성이 되어 있습니다.

만약 신규 배포로 인해서 a서버를 우선 죽이게 됩니다.

그럼 죽이기 전에 우선적으로 a서버에 있는 커넥션들을 B서버로 옮겨주어야 합니다. 그러면 사용가능한 Url값을 이제 b서버 주소를 알려주면서 b서버와 커넥션을 맺게 됩니다.

  • 이떄 사용가능한 툴이 앞서 말한 이벤트 툴이 되겠죠

  • 그리고 참고로 이 방식은 디스코드에서 사용하는 방식 중 하나라고 알고 있습니다. 제가 이 방식을 구현하지는 않았는데 채팅서버 같이 작업하시는 분이 이러한 방식으로 구성한걸로 알고있어요

 

그래서 말을 조금 정리를 하자면, 무중단 서비스를 구성하기 위해서는 인스턴스간에 소통 할 수 있는 툴이 필요하고, 해당 툴을 사용하여 Pub/Sub 모델링을 구성해 필요한 정보를 공유하게 된다.

또한 게이트웨이 router라던지 서버를 구축하여, 해당 HTTP 요청을 통해서 사용가능한 인스턴스를 받게 되고, 이 인스턴스와 연결을 유지하게 된다.

 

이정도가 될 꺼같네요.

제가 아키텍처 설명하는데에는 큰 재주가 없어서.. 생각나는대로 작성은 해보았는데. 이해가 잘 되실지 모르겠네요.. 혹시 이해가 안가시는 부분이 있다면 말씀해주세요. 제가 잘못 전달을 드렸을수도 있으니!!

최태현님의 프로필

최태현

질문자

2024.04.04

안녕하세요!! 정성스러운 답변 남겨주셔서 감사합니다! 🙏

결론적으로

  • scaling 과정이건 이와 유사한 무중단 배포 과정이건, 기존의 WebSocket Connection 들을 새로운 소켓 서버로 옮겨주는 (혹은 적절히 분배해주는) 과정이 필요하고

  • 이때 중간에 Queue를 둬서 Pub/Sub 형식으로 Connection 들을 옮긴다는 말씀이시군요!

    • 아마 Room 같은 객체에 lock을 걸고, DB에 동기화 하고, Pub/Sub을 통해 다른 서버로 WebSocket Connection이 완전히 옮겨가면, 해당 서버가 종료되겠네요!

 

이야~ 이런 부분을 직접 구현하기에는 쉽지 않을 것 같은데, 기술적인 부분을 해결해주는 프레임워크가 있을 수도 있겠네요!

궁금한 부분이 해소되었습니다 😊 정말 감사드립니다.

 

저 그럼 마지막으로 궁금한 부분이

  • 새로운 서버가 떠서, 이제 Web Socket을 이동시키려고 할 때,

    • web socket handshake를 새로운 서버가 클라이언트에 먼저 요청하게 되나요?

    • 아니면 기존의 서버가 client에게 새로운 서버 정보를 넘겨주어 client가 server에게 handshake를 요청하게 되나요?!

결국 A 서버와 연결되어 있던 connection을 B 서버로 옮기는 과정에서 누가 먼저 connection을 열게 되는지 궁금합니다!

질문이 많아 죄송하네요!! 🥺 감사합니다! 🙇

 

 

아! "사용가능한 socket URL을 받은 후에 연결을 하지" 라고 말씀해주신 걸로 볼 때

Client - LB - 서버 A가 있는 구성이라면, Client - LB 간의 connection은 유지되고 LB - 서버 A 대신 LB - 서버 B connection만 갈아끼워주면 되겠군요! client 입장에서는 이동이 있는지도 모르겠네요! 서버가 클라이언트에게 handshake를 거는게 낯설어서 질문드렸는데, 서버 컴포넌트 간에는 누가 먼저 handshake를 요청하건 크게 상관 없을 것 같군요!

넵 맞습니다. 사실상 게이트웨이 타워가 있기 때문에 알아서 분배정책에 따라 브로드캐스팅 됩니다.

 

Wss에 대한 스케일 부분은 굉장히 까다롭고 문제가 많은 부분입니다.

 

현재 저도 실무세서 wss에 대한 무중단 서비스를 구성하는 상황이 있고 사용을 하고 있는데.

 

이런 문제에서 peer문제라던지, connection에 대한 타임 아웃이라던지 꽤나 다양한 문 제가 발생을 하게 됩니다.

 

저 같은 경우는 아무래도 다수의 http요청이 있고 이 후 최종적으로 하나의 rpc서버에서 wss요청을 하는 상황이 있습니다.

 

이런 경우에 대해서 내부 도메인을 많이타다보니 관리가 쉽지 않기도하고 단순한 http 요청이여도 지속적으로 보안을 위해 내부 ip를 바꿔가며 동작을 하기 때문에...

 

그래서 저는 무중단 서비스를 위해서는 어느정도의 비효율을 감안 하는것도 괜찮은 방법이라고 생각을 합니다.

 

개발이라는게 완벽하다면 좋지만 일정에 치이다보면 완벽보다는 완성을 우선시 하는 상황도 많다고 생각을 하기 현재 저는 그런 상황에 놓여있기 때문에

 

그래서 보통 retry조건을 걸던가

너무 자주 peer 끊김이 발생을 한다면 그냥 keep alive 옵션을 꺼버리는 경우도 있습니다.

 

이는 아시겠지만 리소스 문제로 상당히 좋지 않은 방법인데요.

저는 인프라측에서 보안을 위해 어쩔 수 없다는 상황을 전달을 받은 상태라서 이런식의 구현도 생각해보시면 좋을꺼 같네요.

 

아 그리고 혹시 괜찮으시다면 질문 내용을 다른 수강생 분들에게도 소식으로 전달드려도 괜찮을까요?

강의 목표를 넘어서서 영양가있는 대화를 했다고 생각하며 다른 분들도 보시면 도움이 될 꺼 같네요.

 

의견 주시면 감사하겠습니다.

늦은 시간까지 고생이십니다!!

최태현님의 프로필

최태현

질문자

2024.04.05

넵넵 그럼요~ 🙂 좋은 답변 남겨주셔서 감사합니다! 🙏

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.04.04

안녕하세요, 인프런 AI 인턴입니다.

최태현님의 질문에 관하여, “몇천명이 Room 에 동시접속할 수 있도록 설계하려면 어떤 것들이 필요할까요?“라는 제목으로 제공된 질문 및 답변이 긴밀하게 관련되어 있습니다. 이 내용은 수평적 확장과 관련된 내용을 포함하고 있으며, 강의에서는 어떻게 대용량의 소켓 서버를 만들어야 하는지, 또 기술적인 측면에서 어떤 접근 방식을 취해야 하는지를 다루고 있습니다. 또한, 서버 스트레스 관리를 위해 다양한 테스트 진행의 중요성에 대해서도 언급되어 있습니다.

해당 질문에서는 웹소켓 개발을 처음 접하는 상황에서 실제로 몇천 명이 채팅에 동시에 접속하는 가상의 시나리오에 대해 어떻게 확장해야 할지에 대한 의문이 제기되었습니다. 이에 대한 답변으로, 서버의 스트레스 관리를 위해서는 다양한 테스트를 진행해야 하며, 특별히 “wrk” 툴을 사용하여 스트레스 테스트를 진행해보고 조정하는 것을 예로 들었습니다. 이러한 방법은 실제 실무에서 많이 적용되는 방식이며, 메시지에 담길 청크의 크기 등을 고려하여 서버를 설정하는 것이 좋다고 권장하고 있습니다.

질문하신 소켓 서버의 무중단 배포에 대한 구체적인 언급은 없지만, 서버를 확장하는 과정에서 고려해야 할 요소들에 대한 일반적인 가이드라인을 제시하는 데 도움이 될 것입니다.

몇천명이 Room 에 동시접속할 수 있도록 설계하려면 어떤 것들이 필요할까요?에서는 서비스의 스케일링과 관련된 권장사항과 함께, 실제로 고려해야 할 요소들에 대해 상세히 설명하고 있습니다. 이와 관련해서 추가적인 관심이 있으신 경우 해당 링크를 참고하시길 바랍니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

최태현님의 프로필

최태현

질문자

2024.04.04

서버의 부하 테스트 혹은 소켓 서버가 견딜 수 있는 TPS에 관한 질문이 아니라, scale out 방식 자체에 관한 질문이기 때문에 Akaps 님의 답변 기다려 보겠습니다! 😊