꽤 많은 분들이 물어보셨다.
그래서 왜 소켓 게임 서버는 Docker 도입 어려워요?
Docker 자체를 공부하고 사용해본 결과…!
바로 메모리에 상태를 보유하고, 이를 기반으로 응답성을 끌어올리는 방식이 게임 서버의 기본 전제인데, Docker는, 아주 더 정확히는 K8S류의 관리 시스템 다수가, 서비스를 언제 올렸다 내려도 상관없게끔 구현된 stateless한 서버가 기반이기 때문이다.
K8S에서 기본적인 동작으로 레플리카 수를 조정하면, 같은 도커 인스턴스가 그 갯수만큼 조정된다.
여기 언급된 다수의 패턴을 그대로 적용할 수 없다. 전제 조건이 달라서 그렇다.
예를 들어, 소켓 서버의 경우 커넥션이 유실되면 재접속 과정을 거쳐야 된다.
프로세스 재시작의 경우에는 메모리에 캐싱 중이던 내용들이 유실 되게 작성되는 경우가 많다. 이로 인해, 종종 듣게되는 백섭 현상이 발생하게 되는 것이다.
그리고, 게임 서버는 같은 종류의 서버군이 같은 일을 하고 있지 않는 상황에 놓이게 된다.
예를들어, 인벤토리 서버 10개가 떠있다고 했을때 모두 같은 유저의 아이템 및 재화 데이터를 동일하게 보유하는 것이 아니라, 각기 다른 유저의 데이터를 들고있게 된다.
존 서버도 마찬가지인지, 게임상의 지역 위의 유저, 몬스터의 다양한 정보를 실시간으로 담고 있는데, 마찬가지로 메모리에 캐싱 해두고 응답성을 끌어올렸기 때문에 프로세스가 재시작 될 경우 서버 다운으로 이루어진다.
물론 위와 같은 상황은 Docker를 사용하는 것만으로 연관성이 있는 것은 아니지만, Docker를 기반으로한 사용한 컨테이너 기반 가상화 도구를 이용하는 장점과는 조금 거리가 있을 수 밖에 없는 제약사항이라고 볼 수 있다.
물론, K8S의 경우에도 무작정 레플리카 수를 조정하고 스케일 인아웃을 하기보다는 자원 상황에 맞게 스케일 인 아웃을 하고, rolling update를 대비해서 시나리오 작성하고, 각 서비스 라우팅과 처리 중인 오퍼레이션을 대기했다고 종료 하는 등의 보강 작업을 거치게 되지만, 소켓 서버는 그에 비해 해야 될 일이 더 많다라고 볼 수 있다.
그렇다면 어떠한 전략으로 소켓 서버에서 Docker를 사용하면 좋을까?
- 컨테이너 가상화의 장점을 이용한 배포 편의성 측면에서만 활용하는 방법이 있다.
- 물론 그럼에도, Docker로 운용되는 건 맞는 만큼 Docker 기반으로 운용 가능한 준비가 되어있어야 한다.
- 프로세스 재시작 시나리오를 소켓 서버에 맞게끔 강제하고 관리하게끔 해서 이용하는 것이다.
- K8S 같은 도구를 이용할 때에, 종료 절차를 차근 차근 밟은 뒤, 천천히 역할을 위임하는 구조로 구성 해야 한다.
- 메모리에 캐싱된 내용을 지속적으로 동기화해서, 같은 역할을 가진 소켓 서버가 다수가 되게끔 구현하는 것이다.
- 그리드 방식의 P2P와 유사한 접근인데, 이 경우는 클라이언트에서도 커넥션 유실에 대한 처리가 즉시 복구, 혹은 짧은 지연 뒤에 복구가 되는 것을 전제로 복구 로직, 보간 로직이 구현되어야 한다.
사실 대부분 소켓 서버를 이용하는 게임마다 특화된 오케스트레이션 도구를 사용한다.
온라인 게임 시기에는 더욱 그랬는데, 당시 적절하고 적합한 오픈 오케스트레이션 도구가 없어 더 그래왔다.
또한 도커는 로컬 공간이 버려질 수 있음을 근거로 동작하는데, 이에 대비하여 구현되지 않은 어플리케이션은 도입하기 어렵다.
로그가 유실이 없으려면 로그 쉬핑도 반드시 이뤄져야하고, 서비스 가동 중단 명령시에 오퍼레이션 (패킷)을 유실 없이 소화한 뒤, 대기 중인 서비스로 연결 시켜주어야하며, 마찬가지로 메모리에 처리 중이던 내용도 대기 중인 서비스로 연결 시켜야한다.
물론 쉽지 않지만, 이런 대비를 해야 소켓 서버를 Docker 기반 환경으로 옮길 수 있다.
이미 운용중인 대부분의 소켓 서버를 이용하는 서비스는 자체적이던, 기존 도구던 서비스 운용 시스템이 있겠지만, 새로 구축을 해야 하는데 소켓 서버라면 한번쯤 고민 해 볼 내용이라고 생각해 정리해보았다.