서버장애시 서버간 대량의 트랜잭션(동기화?)을 다시 맺어야 할경우..

3권에서 새로 도입된 네트웍 및 멀티플레이어 프로그로그래밍 섹션을 위한 게시판입니다.

Moderator: 류광

Locked
비회원

서버장애시 서버간 대량의 트랜잭션(동기화?)을 다시 맺어야 할경우..

Post by 비회원 »

현재 서비스중인 서버를 개발&운영을 겸하고 있습니다.
아직 안정화가 적절하지 않아서 운영을 겸하고 있는데요.

실제 세션을 맺는 서버는 5대이고..
각 사용자는 로비쪽에서 세션서버쪽으로 분산이 됩니다.

각 서버에 물린 사용자들은 다른 세션서버에 물린사용자들과
통신을 해야하는 일이 있어서..
A라는 서버에 있는 a사용자가 B라는 서버에 있는 b사용자에게 특정메세지를 전달하고자 할경우

A ---------- B
a ---------> b

A라는 서버는 B라는 서버에게 tcp세션을 하나 생성해서 메세지를 보내고
B는 b에게 메세지를 전달합니다.

그래서 각 서버마다 자신이 통신을 해야할 사용자들의 리스트와 그 사용자들이 어느서버에
접속하고있는지에 대한 정보를 같이 저장합니다.
기존구조는 이런것인데..

문제는...

B라는 서버에 장애가 발생해서 문제가 생길경우
b라는 사용자가 B서버에 접속할때 a라는 사용자가 A서버에 있다라는 정보를 가지고 있어야 하는데..

장애후 재시동시 A서버는 이런정도를 B에 보내서 테이블을 구성하게 할려고 합니다.
근데 그러다보니..

서버1대당 동접 1만여명을 생각하는데.. 이럴경우 A서버에 접속하는 사용자들이 100여개의
리스트를 모두 동기화 시키려면 10000(명)x100(리스트) = 1,000,000 개의 동기화
패킷을 보내서 B서버와 동기화를 해주어야 하는데..ㅠ.ㅠ.
이건좀 너무한다 싶기도 하고요..


리스트정보는 수시로 추가, 삭제가 되는 작업이라 따로 DB에 넣어서 동기화를 맞추기도
참 애매합니다..
서버간 통신으로 메모리에 올려놓고 하는게 제일 간편하긴한테.. 이렇게 장애가 발생했을경우
발생한 서버를 재시동이 각 서버간의 동기화를 위한 작업 부하가 큰듯해서요..
B서버는 A서버로부터 정상적으로 동기화를 수행하지 못하면.. 사용자 접속을 받아본들
정상적인 서비스가 불가합니다.

이런경우 서버설계를 다시 수정해야 할런지.. 아니면
서버재시동시 대량의 동기화데이터를 효율적으로 수신해서 빠른시간안에 동기화를 맞추고
새로운 사용자를 위한 서비스를 준비할수 있는지..
고민이네요. ㅠ.ㅠ.

비슷한 고민 해보신 개발자분들 좋은 의견좀 부탁드립니다.
chadr
Posts: 980
Joined: 2003-06-01 12:28
Location: 모대학
Contact:

Post by chadr »

딱히 너무할건 없습니다. 그만큼 필요한 데이터이니 반드시 동기화를 해야하지요.
데이터 크기가 얼마나 되는지 모르겠지만 내부네트워크로 연결되어있고 회선 속도가 빠르다면 그정도 데이터는 순식간에 전송될것이라고 생각됩니다.

그게 부담이 되신다면 한번에 전송하는것이 아니라 B서버가 살아난 후 만약에 A와 B가 통신해야하는 경우가 생기면 그때마다 B가 A에게 관련 데이터를 요청하여 사용자 데이터가 있다면 전송해주고 구축 해주는 식도 괜찮습니다.

한번에 1만명이나 되는 사람이 서버를 넘어서 메시지를 보내는 경우가 발생할 일은 없고(그렇다면 그냥 처음에 1만*100을 전송하는게 낫죠) 조금씩 이렇게 쪼개서 필요시만 전송하시면 큰 부하는 없을 거라고 생각됩니다.
비회원

이렇게 하면 어떨까요 ?

Post by 비회원 »

사용자는 최초 로비쪽에 접속하고.
로비쪽에서 서버5대에 알맞게 분산시킨다는거죠 ?
100여개의 리스트라는것은 한사용자가 가지고 있는 메시지를 보낼수 있는 다른 사용자 리스트 인가요 ? (친구목록같은)

제가 이해한게 맞나 해서요.. ^^;;
그렇다면 굳이
각 서버마다 자신이 통신을 해야할 사용자들의 리스트와 그 사용자들이 어느서버에
접속하고있는지에 대한 정보를 가지고 있을 필요가 있나요 ?

로비 서버를 이용하거나 중계서버(?)를 사용하면 되지 않을까요 ?

예를 드신 A서버 a유저 B서버 b경우.
최초 a유저가 로비서버에 접속 A서버로 배정(?)된 경우 로비서버에서 a유저는 A서버라는걸 저장하고 있고,
b유저 로비서버 접속 B서버로 배정(?)되면 로비서버에서 b유저는 B서버라는걸 저장하고 있으면,
a유저가 b유저에게 메시지를 보낼때.
A서버에서 B서버로 바로 가는게 아니라
A서버는 로비서버로 메시지를 보내고, 로비서버는 b유저가 어느서버에 있는지 확인 B서버로 메시지를 보내면

로비서버가 문제가 생겨 재 시동된 경우 각 서버로 부터 접속된 유저정보만 다시 받으면 되고.

로비서버에서 각 유저가 어느서버에 연결되있는지만 관리해주고 각 서버는 로비서버에게 메시지를 중계시키면 어떨까요 ?
비회원

감사합니다.

Post by 비회원 »

세션과 로비서버는 서로 통신하지 않습니다.
세션서버들과의 통신은 세션서버들끼리 합니다.

로비나 중계를 거쳐서 세션끼리 통신하지 않는구조입니다.
처음에 이 구조로 했다가 구조상 한곳에서 장애가 생길경우 트래픽이 폭주하는
상황이 발생하면서 전체 시스템이 마비가 되서.. ㅠ.


친구리스트같은거는 맞습니다.

즉 A에 a가 있고, B에 b가있을때

a가 A에 접속하면 B에 정보를 보냅니다. 이때 b가 접속하면 a가 보내준정보를 보내는거죠..
만약 a가 100개의 리스트를 가지고 있다면
B가 장애발생후 다시 시동하게 되면 A는 다시 100개의 리스트를 B에게 보내서 동기화를 해야겠죠..


이때 A에 a만이 아닌. 10000여의 유저가 있고 각 유저가 100개의 리스트를 다른서버에 보내서
동기화를 해야한다면..
문제가 생기지 않을까 해서 입니다..


개당 패킷은 3-40byte정도 되겠네요. ㅠ.

휴.. 장애가 안나면 금상첨화지만..ㅠ.
머. 장애시 대처해야할 코딩정돈 해줘야겠죠.ㅠ.
비회원

궁금합니다.

Post by 비회원 »

위에 글쓴이입니다.
정확히 어느 상황에 트래픽이 폭주하는지 알려주실수 있으시면 알려주세요. ^^
메시지 전송시 직접 연결보다 패킷량이 2배가 되긴하지만, 내부연결이면 별문제 없을거 같았는데.
제가 서버쪽 지식이 부족해서. 제생각엔 저렇게 하면 괜찮을거 같았는데.
블루
Posts: 80
Joined: 2007-10-04 10:56

Post by 블루 »

구조를 건드리지 말고 가장 쉽게 성능을 향상시킬 수 있는 방법이라면 .. 동기화 패킷을 보낼대 때 개별 Entry마다 따로 보내지말고 묶어서 보내면 별 문제 없을것 같네요.

예를들어 Entry를 1,000개씩 묶는다면 1,000 x 40 = 40KB정도이므로 무리 없는 크기이고,
동접이 10,000인 경우라도 10,000 x 100 / 1000 = 1,000개가 패킷개수가 되므로 내부 n/w 속도만 충분히 빠르다면 무리없는 수준일테고요

40 byte 짜리 패킷을 100만개 보내는 것은 overhead가 너무 커 보이네요..
비회원

저도..

Post by 비회원 »

entry를 나눠서가 아니라.. 최대한필요한 정보만들 수집해서
재조하후 보내는걸 생각해보긴 했습니다.
역시 패킷량을 최대한 줄여서 빠른시간내에 동기를 맞추는게 제일 좋은 방법일까요?

장애처리가 생각보다 고민할게 많군요.ㅠ.
비회원

중계서버를 통한.. 동기화...

Post by 비회원 »

중계서버를 두지 않는이유는...
중계서버가 모든 클라의 리스트를 가지고 있기에
죽어나가면 전체서비스가 마비가 되기 때문입니다..

그래서 세션서버단에서 개별적으로 처리하게 한것입니다.
트래픽은 한서버가 죽어나가면 중계서버에서 다른 세션서버들에게
이를 알려줘야 하기때문에 트래픽 양이 폭주합니다.

정답은 아니지만.. 제 서버 설계상... 요렇게 되있네요. ㅡ;
블루
Posts: 80
Joined: 2007-10-04 10:56

Re: 저도..

Post by 블루 »

비회원 wrote:entry를 나눠서가 아니라.. 최대한필요한 정보만들 수집해서
재조하후 보내는걸 생각해보긴 했습니다.
역시 패킷량을 최대한 줄여서 빠른시간내에 동기를 맞추는게 제일 좋은 방법일까요?

장애처리가 생각보다 고민할게 많군요.ㅠ.
장애처리를 제대로 하려면 결국 처음부터 거기에 맞춰 구조를 설계해야 하죠.
fault tolerance한 서버를 만든다는게 결코 기능 몇개 추가해서 되는 mission이 아니니까요..

몇년전에 친구목록을 포함한 사용자 관리 서버를 병렬로 배치해서 구현한 적이 있는데, 서버 restart시 동기화는 packet buffer가 허용하는 한계만큼 한번에 보내는 식으로 처리했던걸로 기억하고요.
이렇게 병렬로 배치하면 확장성이 높아지는 대신, 기능이 많아질수록 복잡도가 너무 높아져서 요즘에는 다른 방식을 사용하기는 하지만요.. 아마도 이런 비슷한 작업을 하고 계신것 같네요..
Locked