서버프로그램하면서 데이타를 큐에 넣는 이유를 알고 싶습니다.

hellowee의 이미지

:twisted:
안녕하세요..
이제 서버프로그램을 접하게 되는 프로그래머입니다.
제가 궁금한것 클라이언트에서 send를 하면 서버에서 그 값을 recv를 받는데..그 데이타를 큐를 넣고 뺀 필요가 있는지 궁금합니다.

alsong의 이미지

특별한 이유가 없다면 큐에넣는건 좋지 않습니다.
데이터가 후처리(가령 다음의 메시지에 따라서 데이터를 써야 한다든가..
이런 경우도 보통은 필요한 데이터만 따로 보관하지 전체를 보관하지는
않습니다.)가 필요한 경우가 아니라면 받아서 바로 처리하시기 바랍니다.

참고 하시기 바랍니다.
http://bbs.kldp.org/viewtopic.php?t=20828

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

ssoo76의 이미지

만약 서버가 어떤 request를 받고 그것을 처리하는데 1초가 걸린다고 생각을 해봅시다.

하지만 이 서버는 초당 10건의 request를 네트워크를 통해서 수신할 수 있습니다.

이럴 경우 버퍼링을 하지 않고 1건의 request를 수신하고 처리한 후 다음 request를 처리할려고 할때 아마도 9건의 request는 drop이 될 겁니다. 물론 운이 좋다면 timeout이 있어서 그 안에 수신한다면 아니겠지만요.

이럴 경우 수신하는 모듈은 request를 수신만하고 큐에 push를 하고 처리하는 모듈은 큐에서 하나의 request를 pop하여 처리하면 되겠지요.

큐에서 발생하는 push와 pop은 한번의 lock과 memory copy입니다. 이는 network IO 보다 비교할 수 없는 속도이죠.

물론 쉬지 않고 request가 오는 경우라면 결국은 큐가 overflow가 나겠지만 비정기적으로 request가 수신된다면 적정 크기의 큐로서 drop되는 패킷없이 처리 가능하겠지요...

세상은 하나..........

alsong의 이미지

얼마안되는 시간동안의 버퍼링은 소켓의 버퍼가 해주는 걸로 알고 있습니다.

일반적으로 통신의 경우 타임아웃을 가지게 되어 있습니다.
A라는 서비스를 요구했을때 응답이 늦어 지면...
클라이언트 입장에선 무한정기다릴수 없기때문에 타임아웃(TCP를 이용하거나, 아님 프로토콜에 정의 되어 있던가) 처리를 하게 됩니다.
즉 큐에 집어 넣었다 하더라도 클라이언트 입장에서는 상당한 지연이 생깁니다.
큐에 넣었다 하더라도 TCP의 timeout(아마 바꿀수 있을겁니다.^^)은 없앨수
있으나 서비스 타임아웃이 일어나게 될겁니다.
TCP의 timeout동안에 처리 못할정도의 시간이라면 이미 클라이언트 입장에서는 실패로 봐야 할겁니다.

위의 님이 말씀하신경우는 서비스의 타임아웃이 아주 길때나 notify(응답이 필요 없는)메시지에서는 유용하게 사용할수 있을겁니다.

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

choissi의 이미지

통신용 버퍼를 만들때 주로 환형 큐를 사용합니다..

그 이유중에 가장 큰것은...
send는 한번에 하지만 그 값을 받는 입장에서는
한번에 recv가 안된다는 것이지요

즉.. 한 패킷을 처리하는데 있어서 패킷 사이즈가 크면
recv한번에 다 받지 못해서 우선 소켓 버퍼에 짚어 넣고
패킷이 만들어 졌나 확인하는 과정이 있어서 소켓 큐를 두는 경우가 있고..

또, 한번에 많은 데이터가 발생을 해서..
우선 받아두고 처리해야할 경우가 있죠

저의 회사는 실시간 시세를 처리 하는데,
체결서버기 큐잉을 하는데 그 이유가 체결을 담당하는 녀석이
해당 시세가 날라 왔을때 처리해야할 양이 많다면
놓치는 패킷이 있어서 따로 큐에 저장을 해주고
처리를 합니다...

로그를 보면 대부분 바로바로 처리 되지만..
장중에 체결이 많이나면 큐에 꾀나 쌓여서
빠지더군요. 이런 상황에서 큐가 없으면 그 데이터들을 잃어 버리겠지요..

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

이우중의 이미지

http://www.cs.wustl.edu/~schmidt/PDF/PLoP-95.pdf

슈미츠 아저씨 홈페이지죠~

alsong의 이미지

Quote:

로그를 보면 대부분 바로바로 처리 되지만..
장중에 체결이 많이나면 큐에 꾀나 쌓여서
빠지더군요. 이런 상황에서 큐가 없으면 그 데이터들을 잃어 버리겠지요..

UDP라면 큐잉이 필요하겠지만....

큐에 쌓여 있다는 정도가 어느정도 인지는 모르겠으나 일시적으로 쌓이는거라면
TCP의 경우 데이터를 잃어버리기는 힘들지 않을까 하는군요.
recv의 버퍼가 가득찼다면 send에서는 전송을 더 이상 하지 않을 겁니다.
대기 상태에 있다가 ack가 오면 그때 다시 데이터를 보내게 되겠지요.
send쪽에서 send timeout을 길게 준다면 일시적으로 쌓이는 정도의 처리는
충분히 해내지 않을까 싶습니다. 서버에 추가적 부하도 없습니다.
TCP에는 부하를 관리해주는 처리가 들어 있어서 서버에 추가적 부하도 없습니다.
응답을 줄때까지 클라이언트는 침묵을 지키고 있을테니까요.
간헐적으로 heardbeat만 추가로 발생 되겠죠.

여담입니다만....... 아래는 지우겠습니다. ... 큐잉이라는 보장이 안되는군요

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

moonzoo의 이미지

글쎄요..제가 보기엔

보는 시각의 차이같네요..

send 쪽과 recv쪽의 관리영역(회사등..)이 엄연히 다른상황이라면..

recv쪽을 설계하는 입장에서..

큐잉을 넣어 처리하는 것도 괜찮겠네요..

이미 구축된 send쪽에다가 timeout를 조정한다는건

일단 recv쪽 설계자의 권한밖의 문제 같고..

일다 send쪽에서 보낸 data는 어떤 식으로든 바로바로 받아주고..

recv 처리단에서 버퍼링(큐잉)을 써서 처리하는 것도

socket 버퍼를 채워서 timeout을 발생시키는 것보다

좋은 정책일것 같네요..

mach의 이미지

Quote:
제가 궁금한것 클라이언트에서 send를 하면 서버에서 그 값을 recv를 받는데..그 데이타를 큐를 넣고 뺀 필요가 있는지 궁금합니다.

1) IO 시간 < Processing Time
Queue를 사용하는 이유는 여러가지가 있겠지만, 대표적인것은 IO시간과 프로세싱시간의 갭이라고 할 수 있습니다. 특히, IO시간은 짧은데, 이를 처리하는 시간이 오래걸리는 경우에는 당연히 큐가 필요합니다. 큐는 단순하게 메모리상에서 구현하기도 하지만, 시스템의 용도 및 구현 전략에 따라, 디스크를 액세스하는 데이터베이스 또는 파일시스템상에 구현하기도 합니다. 클라이언트의 입력이 단순무식한데, 서버는 이에대해 섬세하게(복잡하게)처리해야한다면, 많은시간이 필요하겠지요?
이러한 서버로 우리가 가장 잘 알고있는 메일서버를 들 수 있습니다. 메일서버는 사용자들로 부터 메일을 원격지로 전송하라는 송신요청을 받으면, 이를 즉시 보내는 것이 아니고 일단은 자신의 송신큐(디스크)에 저장합니다. 그리고, 주기적으로 보낼수 있을때 보내게되지요. 경우에 따라서는 한통의 메일전송에 4시간이 소요되기도 합니다. 원인은, 원격지와의 네트워크상태불량등 그 원인이야 아주 다양합니다.

2)클라이언트 > 연결관리서버 > 백엔드 서버 구조에서 백엔드서버의 한계
보통 이러한 구조를 3-tier모델이라고 볼수있습니다만, 하나의 사례를 들어보면 백엔드서버가 동시에 허용하는 접속자가 제한이 되어있고, 연결관리서버(보통 앞단에 있어서 FEP:Front End Processor라고도 부릅니다)는 보다 많은 사용자를 수용한다고 가정해봅시다.
즉, 클라이언트 :N
백엔드서버 : M
이때, N >> M이라면, 연결관리서버는 이를 극복하기 위한 어떤 구조를 가져야하지요? 이때도 큐를 쓰게됩니다. 은행창구를 봐도 알수있는사례지요? 이러한 것으로는 미들웨어또는 비슷한기능을 수행하는 것들로 사례로 들수 있겠습니다.

3) IO와 프로세싱의 분리
IO와 프로세싱을 완전히 구분하기 위한 것이라고도 할 수 있습니다. 다음과 같은 시나리오를 생각해볼 수 있습니다.
쓰레드그룹 A : IO처리 쓰레드들
큐큐큐큐큐큐큐큐
쓰레드그룹 B : JOB B처리 쓰레드들
쓰레드그룹 C : JOB C처리 쓰레드들
..............
쓰레드그룹 Z : JOB Z처리 쓰레드들
쓰레드그룹 가 : 모니터링

이러한 시나리오는 보통 다음과 같은 경우에 사용될 수 있겠습니다.
사용자1의 요청을 처리하는 와중에 사용자1의 다음요청을 수신가능하다라는 시나리오라면 더욱 타당하겠네요. 즉, 한사용자의 요청<-->처리를 한단계씩하는것이아니라, 파이프라인 메커니즘으로 사용자의 요청을 연속적으로 받아들이는 시나리오라면 더 그러하겠습니다. 또한 사용자관점이 아니라 JOB처리 쓰레드 관점으로 보면 더욱 그러하겠습니다. 즉, 사용자의 요청처리 쓰레드가 지정되어 있는것이 아니라, "놀고있는 처리쓰레드가 큐에서 가져다가 일을 처리하고 결과를 큐에 가져다 놓는다."라는 것이지요. (개인적으로 저는 이 모델을 선호합니다)

4) 사용자 수준에서 버퍼관리
TCP는 프로토콜스택 내부적으로 흐름제어를 가지고 있습니다. 즉, 자신의 수신버퍼가 가득차면 상대편 컴퓨터에게 잠시 뒤에 전송할 것을 요청합니다.그리고, 상대편은 대기하게되고, 버퍼가 비어져서 전송가능하다면, 다시 전송을 재개하게 되겠습니다.
기본적으로 소켓프로그램을 작성할때는 Blocking모드로 작성하게되는데요. 때에 따라서는 Non-Blocking모드로 작성하게됩니다. 전형적인 사례가 하나의 서버쓰레드(프로세스)가 다수개의 연결을 한꺼번에 받아서 관리하는 구조에서는 Non-blocking을 사용하게됩니다. (물론 다수개를 관리하는 쓰레드가 다수개 생성될수도 있겠지요?)
한 쓰레드가 여러개의 연결을 관리하고 있을때, 쓰레드는 특정사용자연결에게만 프로세싱타임을 소모할 수 없습니다. 즉, 그 사람(연결)때문에 다른 모든 사용자가 block되어서는 안된다는 것이지요. 그래서 이경우에는 Non-blocking으로 서버골격을 만들게 됩니다. 그리고, Non-blocking에서는 사용자 수준에서 버퍼관리를 필수적으로 필요로하게됩니다.
그런데, 문제는 여기서 발생합니다. 송신할 데이터양과 수신할 데이터양을 알 수없다는 큰문제에 봉착하게됩니다. 도대체 어느정도의 양인지?
프로그래머는 이때 이런 걱정, 저런걱정을 해야하지요. 때로는 가정을 마구세워버리기도 하지만요.
이때 큐를 사용하면 그러한 걱정을 덜 수 있습니다.

** 끝으로, queue는 메모리상의 작은 자료구조로 만들어 보는것도 좋습니다만, 저는 그런 방식은 별로 권하고 싶지않습니다. 실시간성이 요구되는 상황도 많이 있지만, 그렇지 않은 사례도 많거던요. 그래서, 데이터베이스나 파일시스템에 큐를 만들어 사용해보는 방법을 권합니다. 성능이 걱정이 되실텐데, 성능 보다는 통신프로토콜용 큐자체를 익히는것을 주관심으로 삼는게 배움의 순서입니다. 성능의 개선은 메모리데이터베이스나, 메모리 자료구조등 또는 memory map등의 테크닉을 사용해서 다소 간은 개선해볼 수 있고, 차후에 시도해도 된다고 생각합니다. 두마리 토끼를 쫒는 실수는 하지 않도록 하는게 좋을듯합니다. 한마리씩 잡아보고, 나중에 둘다를 만족하도록 노력해보시는게 좋을 듯하네요. 큐의 필요성을 배울때는 성능보다는 양(메시지크기)에 초점을 두는것이 배움의 시작이라고 생각합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

liongo의 이미지

제가보기엔.. 질문에 대한 답이 너무 포괄적인것 같습니다..

질문한 사용자는.. 간단한것을 질문한것 같은데.. 물론..

다른 님들의 글내용은 참조하면 좋은 내용입니다.~

제가 하고싶은 얘기는..

특별히 큐를 사용하는것이 나쁘지 않습니다. 물론 구현하는

서버가 어떤일을 하느냐 어떻게 만들것이냐가 문제지..

큐를 사용한다고 나쁜일이 생긴다고 할수 없습니다...

큐는 프로그래밍의 하나의 알고리즘일뿐이니까요..

어떻게 사용하느냐는 프로그래머의 역량에 달린 문제입니다..

실질적으로.. 많은서버들이 큐를 사용하는것을 부인할수 없습니다..

단순히 recv 한 데이타를 그대로 처리하는 문제가 아닌 큐를 사용함으로

써 서버의 객체지향도가 상당히 높아질수 있습니다.. 큐를 사용함으로써

업무단위를 클래스로 정의하고 그것을 큐에다 넣고 처리하는 방법과

같은 기초적인것부터해서 나중에 서버가 멀티쓰라드라든가 논블러킹

등등 의 서버모델로 변환이 용이해지는점도 있습니다..

말이 길어지는군요 제가보기엔. 큐를사용한다고해서 나빠지는 점은

특별히. 없는것 같습니다.. 모 프로그래머의 역량이나 마음이라고 해야할까

^^;; 그럼..

' 형식이 내용을 규정한다. '

익명 사용자의 이미지

큐를 적용하기 위한 조건들... 제 생각일뿐이지만 이럴때는 필요할거 같습니다.

1. 요청에 비해서 그 요청을 해석하는데 상당히 오래걸릴경우. 또는 지연이 발생
- 예> MPEG streamming 받으면서 재생해야 할때.
- 예> 보안접속에 의한 암호화 전송.

2. 특정 크기 이상이 요청되어야 전체 패킷이 해석가능할때
- 예> 블럭 암호화.
- 예> CRC가 뒤에 붙는 프로토콜
- 예> RTSP/HTTP 등 끝을 인식하기까지는 해석이 곤란한 경우.

3. 전송된 데이터가 특정 시간 간격마다 주기적으로 소모될때
- 예> VOD

4. 데이터 유실이 발생할 가능성이 큰 경우
- 예 > 위성통신 (데이터를 꾸준히 받아야 되기 떄문에..)

5. 큐의 단순운영 및 큐의 복사운영
- 큐를 생성하는데는 읽은 버퍼를 그대로 연결리스트 노드에 그 포인터만
대입하는 방법이 있고 다른 방법으로는 복사해서 노드에 넣는 경우가
있습니다. 전자의 경우 큐가 없어도 될곳에 적용하더라도 큰 부하는
발생하지 않지만 후자의 경우는 부하가 증가합니다.
왠만한 경우가 아니라면 전자를 항상 고려해서 만들어 두는것이
좋을듯 하다는 의견을 세워봅니다.

alsong의 이미지

음 많은 리플들이 올라왔네요.
프로그래밍은 어렵고도 험난하군요.
어지러버라 ^^;

큐잉을 하고 안하고의 성능에 얼마나 차이가 있을지 궁금하군요.
객관적인 자료는 없나요 ^^ 아시는분.

그리고 MIS형태의 서버를 제외하고 큐잉을 하는 서버는 어떤것들이 몇가지만 이야기를 ^^;
(가능하면 소스가 있는 것을... 이번기회에 좀 더 파야 겠군요.)

어플리케이션과 TCP사이에 큐를 사용하는 내용의 문서를 찾기가 어렵군요.
(보통 웹으로 찾으면 몇가지가 나오는데 여기 관련내용은 찾을 수가 없네요)
좀 더 이론적으로 접근한 문서가 있는지 알려 주세요.

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

mach의 이미지

Quote:
좀 더 이론적으로 접근한 문서가 있는지 알려 주세요.

동문서답인지 모르겠지만, 미들웨어 관련자료를 찾아보심이 어떨는지요?
미들웨어들은 전형적으로 큐를 핸들링해야하니까요. CORBA같은 분산객체미들웨어 말고도, 메시지관련미들웨어( MPI, PVM)나, MQ Series같은 상용 또는 sourceforge사이트에서 오픈프로젝트로 만들어 보고있는 미들웨어등도 참고가 될수도 있겠네요. 단지 어플리케이션과 tcp사이의 큐만을 가지고 찾으려고 하면 무리가 있으실듯합니다. 소위 전산기초로 배우는 자료구조의 그 "큐"개념만 구현하는 경우는 드물거든요. 이를 테면 로드밸런싱등을 포함하는 경우가 있고, 보다 복합적인 내용을 가지고 큐를 구현하게됩니다. 이런방향으로 자료를 찾으시면, 제법 많은 정보를 찾으실 수 있을것입니다.

* 소스포즈가서 queue치니까, 제법 쓸만한 프로젝트들이 많이 있는것 같습니다. 그들에게서 아이디어를 얻어보시는것도 좋으실듯.
http://sourceforge.net/

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.