다음과 같은 상황에서 어떤 C/S 모델을 선택하여야 할까요?
글쓴이: freestyle / 작성시간: 화, 2007/12/04 - 10:11오전
관리대상이 되는 서버들의 시스템 자원을 모니터링하여
DB를 갖고 있는 한 서버에 데이터를 전송하는 프로그램을 제작 중입니다.
서버는 DB를 갖고 있는 한 대가 되겠고,
클라이언트는 관리대상인 녀석들이 되지요.
특징
1. 클라이언트가 한 번 서버와 연결이 되면, 그 연결을 통해 계속 데이터를 전송한다. 죽을 때까지.
2. 관리대상이 되는 클라이언트의 수는 그렇게 많지 않다. 많아야 십여 대.
3. 전송되는 데이터의 양이 클라이언트마다 1회에 1~2KB이다.
4. 클라이언트는 5초나 10초마다 한 번씩 데이터를 전송한다.
5. 서버는 수신한 데이터를 DB에 저장한다.
특성은 이러한데, 멀티쓰레드, 멀티프로세스, 멀티플렉싱(select로 대표되는..) 중
어떠한 모델을 사용하여야 할까요?
뭐 그렇게 load가 많지 않기 때문에 어떠한 녀석으로 하든
자원에 크리티컬한 영향을 미치지는 않을 것 같지만,
만약 클라이언트의 대수와 전송되는 데이터의 양이 지금보다
늘어났을 경우(그래봤자 수백 KB..)를 고려해 본다면 어떠한 모델이 적합할까요?
아직 초보라 멀티프로세스를 구현하는 것이 보다 쉬워서 그것을 생각하고 있습니다.
연결 수가 그리 많지 않아 context switching시 overhead도 적을 것 같고...
그리고 아직 멀티쓰레드 프로그래밍은 익숙하지 않아서요.
조언 부탁드립니다.
Forums:
수십대이건,
수십대이건, 수천대이건, 가장 자신있는 방법이, 현재 가장 좋은 방법입니다.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
'관리대상이 되는
'관리대상이 되는 서버들의 시스템 자원을 모니터링하여 DB를 갖고 있는 한 서버에 데이터를 전송하는 프로그램'
이런거 많이 있지 않나요?
음
네. 많이 있죠.
그래도 직접 만들어 보는데에 의미를 두려구요...
멀티프로세스로 하려고 했는데, 그래도 공부하면서 만드는 데 의의가 있으니
멀티쓰레드 방식으로 직접 만들어 볼까 합니다. ㅎㅎ
멀티프로세스로 구현시 불필요한 부분(예를 들어 DB에 입력하는 부분)까지 복사하는 것과
context switch로 오버헤드 생기는 게 마음에 안 드네요.
비록 gcc가 이론상의 멀티쓰레드를 완벽히 지원(?)하지 않는다는 이야기가 있고,
워낙 작은 프로그램이니 오버헤드 발생해 봤자겠지만,
어차피 공부하는 입장에서 만드는 것이니 추세(?)라고 할 수 있는 멀티쓰레드로 하렵니다 ㅎㅎ
일단 급한 불부터 끄고 여러 상황을 가정하고 각각을 구현한 다음 스트레스 테스트를 해봐야겠네요.
그래도 '멀티플렉싱' 요녀석은 도대체 왜 쓰는지 모르겠군요 +_+
멀티프로세스의 오버헤드(fork)를 줄이기 위한 녀석같긴 한데...
----------------------------------------------------------------------------------------
Don't Feed the Trolls!
----------------------------------------------------------------------------------------
공부차원의 토이프로젝이라면은
자신있는 방법을 쓰는것도 괜찮지만
학생때 최대한 많은 삽질을 해보는것도 좋은 경험이겠죠?^^
학생때는 모르는게 용서가 되지만은.. 또 모르는것에대한 책임을 거의 혼자서 지지만..
사회에서는 용서가 잘 안되니까 말이죠; 책임도 공동으로 지구요
소켓 통신 부분은
소켓 통신 부분은 멀티플렉싱으로 하고 디비 입력 부분은 따로 쓰레드를 돌리는 것이 좋을듯 하군요.
멀티쓰레드로.. 쓰레드가 수천개되면 ㅎㅎㅎ 한번 해보세요.
요즘.. CPU 가 좋긴하죠 -0-;;;
그리고 프로그래밍 적으로 공부를 한다면.. 차라리 저는 멀티플렉싱을 공부하라고 해드리고 싶군요.
libevent 같은것의 소스를 듣어보세요.
-------------------------------------------------------------------------------------------------------
Life ... http://iz4u.net/blog/
------------------------------------------------------------------------------------------------
Life is in 다즐링
일반적으론, 그런
일반적으론, 그런 경우 client 가 server로 데이터를 쏘기 보다. server가 client에게 접속해서 요청을 합니다.
즉 생각하시는 server와 client가 서로 뒤바뀌지요. snmp가 그 대표적인 예이구요.
뭐 위에 이야기는 그렇다 치고.
생각하시는 구조에서라면, 전 통신을 하는 쓰레드와 DB에 기록하는 쓰레드로 나누고, 통신하는 쓰레드는 non-block 소켓을 이용한 async 통신을 통해 데이터를 수신하여 DB 작업 쓰레드와 통신 할 큐에 기록할 데이터를 enqueue하고, DB 작업 쓰레드는 큐를 모니터링 하다가 큐에 들어오면 DB에 기록하도록 하겠습니다. DB가 빠르다면 DB작업 쓰레드를 여러개 두면 될거고, 이렇게 하면 client가 증가해도 빠르게 잘 작동 할겁니다. 1 client 당 1thread로 간다면 client가 수백~수천이 되면 비효율적이 되는데 이문제를 제 경우는 1thread에 async 통신을 통해 다수의 client를 처리하므로서 쌈박하게 해결 하겠습니다. ㅎㅎ
공부하시는 입장이라고 하니, 쓰레드간 통신을 위한 큐의 구현시 condition 이라는 것과 condition signal 이라는 걸 이용해서 구현한다는 첨언을....
그리고 gcc와 쓰레드 지원과는 상관없습니다. thread 라이브러리의 문제이거나 커널의 문제이지 컴파일러의 문제가 아니죠.
...
multiplexing은 다중화라고 하지요.
TDM(Time Division Multiplexing), CDM(Code Division Multiplexing), FDM(Frequency Division Multiplexing)등등을 그 사례로 들 수 있습니다. TDM은 주로 실시간 시스템에서 사용되며, CDM은 ....., 음,.. CDMA, 많이 듣던 얘기지요? FDM은 구형 무전기, 라디오, TV등을 그 사례로 들 수 있겠습니다.
x닉스 시스템에서 select, poll, epoll, kqueue등의 멀티플렉싱은 주로 IO의 관점에서 이뤄집니다. 동시에 다수개의 IO를 제어하기 위한 메카니즘이라고 할 수 있습니다.
유닉스는 전통적으로 모든 장치를 파일로 추상화해서 바라보는 관점을 제공합니다. IO의 경우(레귤라 파일, 소켓등)에도 파일로 바라보는 관점을 제공하는데, 만일 동시에 IO를 대기하고 있는 장치/파일이 다수 개라고 가정해 보면, 어떤 시점에 IO가 가능해질지 예측하기 어렵습니다. Output시점은 예측할 수 있을 지 모르지만, 원격지가 받을 수 있는지?(보낼수 있다는 것인지?)등을 아는 것은 단순하지 않습니다. 예를들어, 1개의 서버에 2개의 통신 클라이언트가 통신한다고 가정하면, 2개의 클라이언트 중 어느 것이 먼저 서버측으로 입력할 지(서버입장에서 Input이 있을지)예측하기 어렵습니다. 또한, 반대로 원격지가 사정상 데이터를 수신하지 않고 지연하고 있는 경우, 송신자입장에서 언제 데이터를 송신할 수 있는지 예측하는 것은 어렵습니다.
이런 경우를 위해 각각의 IO 단위에 대해 busy waiting하는 방법이 있을 수 있고, IO가 가용(available)한 것에 대해서만 IO를 수행할 수 있겠습니다. 전자, 즉, busy wait하는 방법은 전형적으로, 멀티프로세스/멀티쓰레드로 구현하게되며, 후자의 경우 이벤트 메커니즘에 의하게 되는 경우가 많습니다. 하드웨어라면 interrupt에 의존적으로 할 수 있겠지만, x닉스는 하드웨어를 추상화했으므로, 이 경우를 위한 IO multiplexing메카니즘을 제공하게됩니다. 즉, 질문자께서 언급하신 select로 대표되는 그러한 것들 입니다.
즉, 소수개(심지어 1개)의 프로세스/쓰레드로 다수개의 IO를 처리(IO가 가능한 원격지와 통신)하기 위한 메커니즘의 하나라고 생각하시면 되겠습니다.
다른 방법으로는 polling이 있는데요, 이는 IO 호출시 블록킹으로(요청이 이뤄질때까지 멈춤)하지 않고, 호출 시점에 가용한 데이터에 대해서만 처리하고, 가용하지 않거나하면, 즉시, 리턴하는 방식을 의미합니다. 즉, non-blocking처리입니다. (참고로, x닉스의 시스템호출은 blocking방식과 non-blocking방식이 있습니다. 이러한 호출의 모드 변환은 프로그램으로 가능한 경우가 있습니다. blocking방식은 호출이 성공/실패하거나, 시그널이 발생시 리턴하게됩니다.) 그러나, 이러한 논블록킹 방식은 CPU를 자칫 과용할 수 있으므로 세심한 테크닉이 요구됩니다. 또한, 이 경우에는 특히, IO의 경우 버퍼관리를 커널에게 위임 하지 못하고, 사용자 프로세스에서 전담하여 처리하여야 하는 부담이 있을 수 있습니다.
이상에서 언급된 메커니즘들을 조합하여, 다수 개의 서버 프레임워크를 만들 수 있겠습니다. 적절한 개수의 프로세스와 적절한 개수의 쓰레드로 이루어지고, 적절한 멀티플렉싱 메카니즘을 도입하면 좋겠으나, 이는 응용 및 디플로이 환경에 따라 다소 차이를 보일 수 있습니다.
어쨌거나,... 그래서.... 좋은 방법은 무엇인가? 고민해 볼 수 있습니다. 답은 그때 그때 다른데, 역시나, 본인이/프로그래머가 가장 자신있는 메커니즘이 가장 좋은 방법이라고 생각합니다.
* select, poll, epoll, kqueue등의 인터페이스가 많은 것은 기술이 진보해야 하기 때문입니다. 이중 select와 poll은 호환성이 좋으나(표준), 그외의 것은 운영체제별로 각자의 성능을 올리고자 만든 메커니즘입니다. 따라서, 호환성을 중시하는 프로그램에서는 전자를 임베디드등 특정한 경우에는 후자를 선택하면 되겠습니다.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
질문입니다. 한 가지 더 고민 중 입니다.
먼저 답변 감사드립니다.
혼자 잘 모르는 상태에서 준비하는 거라 정말 막막합니다.
기한은 올해 끝나기 전까지인데..
이전에 질문드렸듯이 관리대상의 서버들의 시스템 자원과
기본적인 정보들을 하나의 DB 서버(mysql)로 받아서 처리하려고 합니다.
현재 단순히 한 클라이언트로 TCP 소켓 하나 생성해서 직렬화시킨 모니터링 데이터를 보내어
DB 서버에서 받는 것까지는 성공했습니다.
이전의 답변을 참고하여 소켓을 non-block 모드로 변경하고,
select로 멀티플렉싱하여 비동기식으로 여러 클라이언트의 접속과 수신되는 데이터를 받아
DB에 저장하는 쓰레드에 던져줘서 계속 저장만 하도록 할 생각입니다.
그런데 이렇게 DB에 저장하는 이유가,
이더넷으로 연결된 임베디드 단말기(무선 모듈을 구하지 못해 그냥 이더넷으로 물리기로 하였습니다)로
모니터링 하기 위한 것입니다.
이 때 여러 단말기로 접속해 각각 보여주는 상황은 배제하여,
하나의 전용 단말기로만 볼 수 있도록 할 것입니다.
현재 임베디드 단말기의 기능은
MONITORING - refresh하여 보여줄 process list, CPU load, MEM, DISK FREE, 접속한 사용자 등
INFORMATION - cpu 등 장치정보, kernel version, booting time 등
OPERATION - (이번 프로젝트에서는 구현하지 않음)
로 구상하고 있고, MONITORING과 INFORMATION은 각각 5초, 5분마다 재전송하려고 합니다.
이제 질문.. ;;;
이 때, 임베디드 단말기로 데이터를 보내야 하는데
다른 프로세스로 포트를 하나 더 열어서 임베디드 단말기와만 통신하면서 정보를 뿌려주는 게 나은지
아니면 그 프로세스에서 임베디드 단말기 전용 쓰레드를 생성하여 DB에서 꺼내서 뿌려주는 게 나은지
(이 때 쓰레드끼리 하는 일이 다 틀리기 때문에 크게 신경써야 할 부분은 없을 것 같은데요..)
고민 중입니다.
약 10대의 관리서버가 5초마다 각각 1~3KB의 데이터를 쏜다면,
임베디드 단말기는 5초동안 최대 30KB를 받게 될텐데
받아서 현재 필요한 정보만 파싱해서 GUI로 보여주고 나머지는 버리려고 생각 중입니다.
참고로 이번에 사용하는 임베디드 단말기는
실습용 키트로, XHYPER270-TKU로 인텔 CPU에 800MHz쯤(맞나?) 됩니다.
조언 부탁드립니다. ^^;
----------------------------------------------------------------------------------------
Don't Feed the Trolls!
----------------------------------------------------------------------------------------
댓글 달기