• 2008-11-02

    Weekends Idle Thoughts

    AQUA, Anantara, Maldives.

    오랜만에 사건 사고 없는 한가한 주말이다.

    먼저 boost asio 를 이용해서 이상적인 아름다운 윈도우 서버 코어를 만든다면? 이라는 상상의 나래를 펴봤다. 누가 봐도 멋진 서버 코어가 되려면 어떤 특성을 가져야 할까?

    • 손쉬운 확장성 : 한대의 머신에서 하나의 프로세스로 1천명에서 최대 1만 명을 처리할 수 있도록 확장하는데 무리가 없어야 한다. 즉, IOCP 핸들와 Non I/O Worker 쓰레드를 M:N 으로 조합할 수 있는 구조가 되어야 한다.
    • 이벤트 기반 : 사용자가 늘어나면 폴링은 최대한 피해야 한다. 즉 주기적으로 체크해야 하는 Idle Check 같은 코드들은 타이머 쓰레드에서 Post 시켜야 한다.
    • 메모리 풀 기반의 버퍼 관리 : 입출력 버퍼를 세션이나 소켓과 1:1 정적으로 매핑시키기 보다는, 메모리풀에서 필요할 때마다 주고 받는 구조를 쓰자. Gathering & Scattering 을 위해서는 필수적이다.
    • 버퍼 복사의 최소화 : 어차피 1-recv 는 대세다. 즉, WSABUF를 개별 세션에 연관짓기보다는 메모리 풀에서 관리하고, I/O 쓰레드에서 입력이 완료되었을 때 메시지가 온전치 않으면 버퍼를 재사용해서 다시 요청에 들어가고, 아니면 새로운 버퍼를 게임 쓰레드로 넘기자. 브로드캐스팅할 때에도 버퍼 복사 없이 하나를 사용할 것! 출력의 경우라면 N-Send 를 쓸 수 밖에 없겠다.
    • 동기화의 최소화 : 쓰레드간 통신은 lock free queue 를 사용해야 한다. 
    • 쓰레드의 최소화 : 서버간 통신, UDP, 추가적인 listen 소켓이 생겨도 쓰레드를 더 만들지 않을 수 있게, IOCP 를 최대한 활용해야 한다.
    • 멀티 코어 대응 : 단지 쓰레드를 많이 만들어서 적당히 잘 돌아가려니..하기 보다는 멀티 코어를 효율적으로 활용하는 방법을 고민해보자.
    • 서비스 기반 아키텍처 : ACE의 그것처럼 서비스를 하나의 프로세스에서 돌리다가 필요하면 다른 서버로 옮기더라도 무리없는 구조가 되어야 한다.

    광고성 글이지만 일전에 c10k 라고 서버 코어를 괴롭히는 스트레스 테스트 클라이언트 프레임워크를 구글 코드에 만들어뒀는데 boost asio 테스트만 하다가 중단된 상태다. 대충 아래 그림과 같은 건데...

    http://farm2.static.flickr.com/1106/1248922047_20af4a2d8c_o.jpg

    이런 걸 구글 app engine 으로 만들고 웹으로 요청하면 쓰레드 1만개 정도 만들어서 서버에 패킷을 보내면 괜찮을 거 같은데... 과연 구글에서 허용할까? (아마 SDK 레벨에서 쓰레드 생성이 막혀 있을 것 같다.) 만약 가능하다고 하면 대충 웹페이지에다가 서버 IP/Port 를 입력하고 테스트 시작을 누르면, 각 테스트 케이스들을 실행하고 성공/실패 여부를 화면에 출력해주는 느낌일 것 같다. (emule 에서 웹 기반으로 TCP 포트 체크하는 거랑 비슷한 거다) 헉. 역시나 찾아보니 안된단다.

    An App Engine application cannot:
    
     - write to the filesystem. Applications must use [the App Engine datastore](http://code.google.com/appengine/docs/datastore/) for storing persistent data. Reading from the filesystem is allowed, and all application files uploaded with the application are available. (Files uploaded as "static" files are not kept on the filesystem.)
     - open a socket or access another host directly. An application can use [the App Engine URL fetch service](http://code.google.com/appengine/docs/urlfetch/) to make HTTP and HTTPS requests to other hosts on ports 80 and 443, respectively.
     - spawn a sub-process or thread. A web request to an application must be handled in a single process within a few seconds. Processes that take a very long time to respond are terminated to avoid overloading the web server.
    
     - make other kinds of system calls, such as [signals](http://www.python.org/doc/2.5/lib/module-signal.html).
    

    그나저나 Windows Server 2008 에는 CreateThreadpoolIo() 라든지 GetCurrentProcessorNumber() 같은 해괴한 API 들이 많이 추가된 모양이다. 어디 새로 추가된 API 목록  정리된 페이지 같은 게 없을까?

    구글 막대 그래프 예제

    다음 잡상은 구글 가젯, 구글 스프레드시트 API, 구글 차트 API로 야구 핵을 만들어보자 라는 글을 보고 떠올린 생각.

    서버 개발을 하다 보면 효율적인 리포팅에 대해서 한두번쯤 고민해본다. 수없이 쌓이는 개발자 로그라든지, 동시 접속자나 아이템 판매량 등등의 통계 그래프라든지, GM들에게 노출할 다양한 사용자 액션 추적 기능 같은 것들이 있을텐데, 이런 걸 구글 apps 기반에 통합해버리면 어떨까 하는 생각이다.

    요즘의 추세는 온라인으로 이 모든 정보를 확인할 수 있는 웹 기반 솔루션을 만드는 것일텐데, 그렇다면 가젯으로 만들어서 구글 시작 페이지에 넣고 권한 관리를 해버리면 되지 않을까? 자자. 이건 상상이니까 안되는 이유에 대해서는 고민하지 말자.

    전사적으로 수많은 서버들의 상황을 한번에 모니터링하기에는 꽤 괜찮은 솔루션일 듯하다.  (물론 MS의 리포팅 서비스가 더 멋지긴 하겠다만..)

  • 2008-10-27

    Blob Quiz

    http://upload.wikimedia.org/wikipedia/en/d/df/The_Blob_poster.jpg요즘 고민하고 있는 문제인데, 보안상의 이유로 비유적으로 설명해보겠다. (실제로 이런 일을 하고 있는 건 아니다 -_-)

    이글아이처럼 우리 국정원에서도, 1분 정도의 음성 통화를 대충 100K 로 압축할 수 있는 압축 알고리즘을 기반으로 하는 휴대폰 통화 감청 시스템을 구축한다고 가정하자.  하루에 10 테라바이트 씩 쌓이긴 하지만, 당연히 각 통화 데이터 끼리의 연관성은 없고, 오직 2개의 송신/수신 전화번호의 키값으로 구분될 뿐이다.

    모든 데이터들은 프라이버시 보호보다는 HDD 부족으로 2주 정도만 지속되며, 오직 리만브라더즈 2명만 들을 수 있다. 물론 둘 다 바빠서 아무도 듣지 않을 수도 있지만, 그래도 무조건 남기긴 남겨야 하는 이 프로젝트를 당신이 맡게 되었다. (아싸 비유를 만들어내는 게 더 리얼하구나~)

    문제는, 연기금을 모두 주가 부양에 써버린 나머지 PC 조립 서버 몇 대만으로 최대한 싸게 구현해야 한다면, 어떤 솔루션을 선택해야 할까? (한줄로 요약하면, 자잘한 BLOB 들이 산더미처럼 만들어질 때의 안정적인 관리 및 검색의 문제인데 검색의 비중이 상당히 낮은 케이스라고 할 수 있다.)

    • 파일 시스템 : 분산 컴퓨터들의 RAID로 보호되는 파일 시스템에 남기고, 검색은 그냥 폴더명으로.. 백업이 없어서 좀 무섭다.
    • 파일 시스템 + 복제 : 안전을 위해 남기는 넘과 읽는 넘을 분리. 안 읽는 넘도 복제해야 한다는게 좀 아깝지만.
    • 분산 데이터베이스 : blob insert 는 좀 힘들지만 어쨌든 검색은 쿼리다.
    • 분산 데이터베이스 + 복제 : 역시 불필요한 복제의 딜레마는 마찬가지.
    • 분산 파일 시스템 + 데이터베이스 : 검색은 파일 시스템, DB는 2차 백업으로... (이건 오버인가;;)
    • 기가비트 이더넷 + HTTP : 분산 컴퓨터들을 기가비트 이더넷으로 묶고, HTTP 서버가 공유 폴더로 인식, Rest 방식으로 다운로드
    • in-memory 테이블이나 데이터베이스: 어차피 용량의 한계로 안될 듯!

    그러고보면 팝폴더 같은 파일 공유 서비스 회사에서, 어떻게 데이터를 관리하는지 궁금해지는구나.

    추가:

    배래군의 조언에 의하면

    • memory mapped file을 사용하려면 거의 무한한 크기를 지원하는 64비트 버전을 사용할 것
    • 사용자 증가로 인해 시스템을 확장할때 스트레스 받지 않는 방법을 사용할 것. 안그러면 lock-in 됨.

    분산 환경에서도 일관성있게 접근하려면 아무래도 중앙 집중화된 DB 인데, 용량의 제약이 있으니... 뭔가 하나의 URL로 분산된 컴퓨터들 어딘가에 저장된 리소스를 한번에 가져올 수 있는 솔루션이 뭐가 있지? 

    큰 flat 파일 안에 트랜잭션을 지원하는 small blob bulk insert & rarely select 가 빠른 무언가가 필요하다. 가상 파일 시스템중에서 찾아봐야 할까나~ 아니면 sqlite + virtual table + memory mapped file 라도 테스트해봐야 하나..

  • 2008-10-24

    Variadic Macros

    GCC 3.0 과 Visual Studio 2005 에서부터 지원하는 가변인자 매크로는 VA_ARGS 로 치환된다. 알고보니 이게 1999년도에 제정된 C99 표준안중 하나였다는데, GCC에서는 약간 다른 방식도 지원했던 모양이다.

    #define MY_LINUX_LOG(fmt,args...) printf(fmt,##args)
    
    #define MY_WIN_LOG(fmt,...) printf(fmt,__VA_ARGS__)
    

    뭔가 있었던거 같은데 도저히 기억도 안나고 오후 무렵에는 인터넷도 안되어서 그냥 __noop 로 고쳤는데, 집에 와서 찾아보니 MSDN 전처리기 섹션에 버젓히 자리잡고 있었다. 쩝. (늙은건가!) 이 외에도 오늘 마이그레이션 과정에서 겪었던 내용을 조금 정리해보면...

    • func / PRETTY_FUNCTIONFUNCTION : 이런건 #define 으로 해결 가능하다.
    • sleep() 과 Sleep() : 초단위 계산 잘못하면 CPU를 99% 잡아먹는다. 헤헤.
    • gettimeofday() 는 리눅스에서만 지원한다. 윈도우에서는 직접 구현해야 한다.
    • random() 과 rand()
    • 매크로를 이용해서 모든 .cpp 에다가 #stdafx.h 붙이기 -_-;
    • buffer overflow 가 자주 발생하는 패턴을 정규식으로 찾아내서 일괄적으로 버퍼 크기 증가시키기

    그 중에서도 압권은 바로 variable length array 일 것이다. 물론 이건 GCC 에서만 가능한 일인데, 내일 출근해서 std::vector 로 고치고, 경고 레벨4로 다시 컴파일해봐야겠다. 

    void func(int n) {     float vals[n];     //.... }

    그나저나, 일본에는 40살이 넘어도 리눅스에서 서버 프로그래밍을 한다던데... 웬지 그런 사회 풍조가 부러울 따름이다. 분명히 그 아저씨의 책상 옆에는 콜라 캔들이 정리되어 있고, vi 로 코딩하다가 make 걸어놓고 네트핵을 즐길 것 같은데 말이다.

    요즘 네트핵은 이정도다!

    어쨌든, 이로서 오늘 시작한 리눅스에서 윈도우로의 마이그레이션은 내일중으로는 완료될 듯!!

    ps. 오늘 드디어 변태군의 야심작 프리우스 온라인이 대망의 오픈 베타에 들어갔다. 회사에서 누가 해보길래 은근슬쩍 "제 후배가 이거 만들었어요" 라고 자랑을 하긴 했는데... ㅋㅋ 초반 다운 안되고 무사히 서비스되기를 기원해본다.

  • 2008-10-22

    Tracking Solution Item

    http://boxcatstudio.files.wordpress.com/2009/07/vs_option.jpg

    현재 편집기에 선택한 문서를 솔루션 탐색기에서 찾아주는 옵션이다. 프로젝트가 여러 개이거나 폴더 트리가 깊을 경우 유용하다. (Visual Studio 2005 이상)

    아시는 분들도 꽤 많으시지만, DDD(Debugging Driven Development)의 창시자이신 모군도 모르는 옵션이라고 해서 한번 써본다.

    ps. 소니군이 최근 미국 불황의 여파와 중국 올림픽 덕분에 캔슬된 비운의 프로젝트의 스크린샷을 공개했으니 한번쯤 구경해주시기 바란다.

    [caption id="" align="aligncenter" width="500" caption="Real Baseball 2009(Ceased)"]http://cfs15.tistory.com/upload_control/download.blog?fhandle=YmxvZzk4OTRAZnMxNS50aXN0b3J5LmNvbTovYXR0YWNoLzAvMC5qcGc=[/caption]

  • 2008-10-22

    Edit & Pray

    http://web.mit.edu/cat/Desktop/cat/images/pray.jpg

    Changes in a system can be made in two primary ways. I like to call them* Edit And Pray *and *Cover and Modify.* Unfortunately, *Edit and Pray* is pretty much the industry standard.
    
    --Michael C. Feathers
    
    

    TDD를 쓰지 않는 대부분의 프로그래머들은 Edit &Continue 보다는 Edit & Pray 를 더 사랑한다. 물론 나도 컴파일러와 윈도우 커널와 쓰레드들에게 자주 빌기도 하지만, 언젠가부터 테스트 없이 일을 진행하면 아무리 실행이 잘되어도 마음 한구석이 편치 않게 되는 경우가 많아졌다. 테스트 통과 후 커밋할 때의 쾌감에 중독되었기 때문인데, 사소한 것까지 테스트한다고 잔소리를 들은 후에야 겨우 벗어날 수 있었다. 그래서 요즘에는 라이브러리 학습이나 개인적인 프로젝트에서만 테스트를 활용하고 있다. 

    최근, 새 프로젝트에서 한정된 시간안에 핵심적인 로직을 제외한 나머지 - 플랫폼, 데이터베이스, 네트워크 프레임워크 외 다수- 들을 마이그레이션하면서 성능과 안정성을 동시에 만족시켜야 하는, 그야말로 도전적인 과제를 맡았다. 이 세마리 토끼를 한방에 잡아주는 은총알이 없는 거야 당연하지만, 그렇다고 점진적으로 리팩토링해나가면서 지켜보는 것도 불가능한 상황이다. 비유적으로 말하자면, 새로 논밭을 사서 농사를 대충 짓다가 적당히 직불금을 받아먹은 후 양도세를 면제받은 후(응?), 기존의 집을 그대로 들어 올려서 새 토지에 얹어 놓고, 인테리어를 막판에 갈아 엎는 대공사를 할 수 밖에 없을 것 같다. 물론 기도를 빠뜨리면 안되겠지만.

    어쨌거나 기회가 되면 google test를 써보고 싶은데, 이 대운하에 버금가는 공사에서 가능할 것인지 나도 참 궁금하다. 쉬귀군이 밥먹다가 말한 것처럼 삽질이 되면 안되는데... 후덜덜.