Fluentd - Pluggable log collector

이미지
 지난번에 소개했던 글 에서 여러 가지 log aggregator들을 소개했었다. 이번에는 그중에서도 특별히 마음에 들었던 fluentd를 더 자세히 소개해 보도록 하겠다. Semi-structured log http://blog.treasure-data.com/post/13047440992/fluentd-the-missing-log-collector-software  우선 fluentd의 가장 큰 특징은 log를 time/tag/record형식 의 semi-structured 형식으로 저장한다는 것이다.  시간은 event가 발생한 시간으로 event를 fluentd로 넘겨줄 때 시간을 같이 넘겨주지 않으면, fluentd에서 받은 시간을 기록하게 된다.  tag는 이벤트를 만들 때 넘기게 되어 있는데, fluentd에서 사용하는 값이다. 이에 대해서는 config를 어떻게 하는지 설명하면서 설명하도록 하겠다.  record는 사용자가 저장하려고 했던 값들로 json 형식의 key/value pair로 저장된다.  semi-structured라고 해도 record가 json 형식으로 저장되기 때문에 원하는 형식대로 저장할 수 있다. Use case  fluentd는 config파일을 바꾸는 것만으로도 여러 머신들 간의 설정을 쉽게 바꿀 수 있다. http://blog.treasure-data.com/post/16034997056/enabling-facebooks-log-infrastructure-with-fluentd  위의 그림은 가장 기본적인 형태로 frontend에 붙어 있는 fluentd에서 보내는 이벤트를 중개 서버(?)에 해당하는 fluentd에서 한번 수집하여 최종 저장소에 보내는 형태이다.  위의 그림은 특별히 fluentd의 성능을 고려하여 하나의 중개 서버가 너무 무리하는 일 없도록 여러 개의 중개 서버에 나누어서 보내는 방식이다. http://docs.fluentd.org/articles/high-avai

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

이미지
https://docs.google.com/presentation/d/12A5RlMCVDN6tA_zUnLrZ0TN5v08gz2GhlRdzxy3T3mU/edit?usp=sharing  회사에서 최근에 Log aggregator system으로 무엇을 사용해야 할지 조사해본 자료다.  우선 log aggregator가 무엇인지 한 문장으로 설명하면, 여러 머신에서 쌓인 로그들을 한 번에 분석할 수 있도록 수집하여 주는 시스템을 말한다.  요새는 특히나 클라우드 시스템이 유행하면서 같은 일을 하는 시스템임에도 다른 머신에서 돌아가는 일이 많아지면서 필요성이 크게 증가하였다. 이번 조사로 알게 된 것들을 적어보도록 하겠다. Scribe  우선 scribe 는 Facebook에서 제작하고 사용하던 log aggregator system이다. scribe:  http://www.cnblogs.com/brucewoo/archive/2011/12/13/2285482.html  후에 다른 로그 수집 시스템들을 보면 알겠지만, Scribe는 다른 시스템보다 간단한 구조로 되어 있다.  Scribe는 일종의 message queue와 message queue에 쌓인 message를 DB에 저장해 주거나, DB가 실패하였으면 local에 저장하였다가 DB가 복구되었을 때 다시 DB에 저장해 주는 것만을 책임진다. 다시 말하면, message queue에 실제로 메시지를 보내는 부분은 사용자가 직접 작성하여야 한다는 것이다.  흔히들 말하는 scribe의 장점은 c++로 만든 만큼 다른 시스템들의 3~5배 정도의 성능을 보여준다는 것이다. 하지만 실제 scribe 사용자들은 무엇보다도 Facebook이 실제로 사용하였던 솔루션인 만큼 성능과 안정성에서 신뢰도가 있다는 것을 장점으로 뽑는다.  하지만 나는 scribe를 사용하는 것을 추천하지는 않는다.  일단 가장 큰 문제는 더이상 Facebook이 Scribe를 사용하지 않는다는 것이다. Faceboo

Actor model and akka

다음 프로젝트로 scalable 한 게임 서버프레임워크 구현을 진행 중이다. 아직 구상 중이라 결정된 것은 없지만, scalability와 functional 한 특성을 동시에 살릴 수 있는 scala 의 akka프레임워크 가 후보로 들어왔고 이에 대해 간단하게 정리하여 발표할 기회가 있었다. 일단 발표자료 는 간단하게 키워드들만 적었기에 이에 대해 보충 설명을 해보고자 한다. akka는 무엇인가  akka는 scala로 구현된 concurrency 제어를 위해 actor model을 도입한 프레임워크로 java와 scala API를 제공한다. 우선 akka는 actor model을 기본으로 하고 있기 때문에 akka의 특성을 이해하려면 actor model을 이해해야 한다. Actor의 특징  actor model은 간단히 설명하면 behavior, state, mailbox로 구성된 actor를 기본 단위로 하는 message processing을 이용하여 behavior를 비동기적으로 실행하는 model이다.  이때 기본단위가 되는 actor는 몇 가지 특징이 있다. 우선 각 actor는 서로 간에 공유하는 자원이 없고 서로간의 state를 건드릴 수 없고, 오로지 message를 이용해서만 간섭할 수 있다.  message는 mailbox에 쌓였다가 들어온 순서대로 처리된다.  실행되는 behavior는 message에 의해 결정되고, 할 수 있는 일은 자신의 state를 바꾸거나, child actor를 만들거나, child actor를 죽이거나 다른 actor에 message를 보낼 수 있다.  actor model의 actor는 사실 OOP에서 말하는 object와 매우 비슷하다.  object는 member variable(state)을 가지고 있고, 어떤 방식으로 동작할지 method(behavior)를 가지고 있다.  method는 다른 object를 만들거나, 자기가 관리하는 object를 부수거나 다른 object의

[html5-lint] console에서 html page validate하기

 WebPage를 스펙에 맞게 작성하였는지 http://html5.validator.nu/ 를 이용하여 쉽게 확인할 수 있다. 하지만 이런 방식은 웹 페이지에서 확인하는 방식이기 때문에 autotest를 만들기 어려워진다. 모질라에서도 같은 고민을 하였는지 auto test를 위해 python과 node.js에서 사용할 수 있는 html5-lint 라는 것을 만들어서 사용하고 있다. html5-lint는 validator를 다시 구현하는 방식이 아니라  http://html5.validator.nu/ 로 post request를 날려 결과를 가져오는 방식으로 동작한다.  하지만 이렇게 하면 테스트할 때마다  http://html5.validator.nu/ 에 request를 요청하게 되므로 모질라에서는  클론 페이지 를 만들어서 사용하고 있었지만, 지금은 클론 페이지가 죽어서 다시 원래의  validator.nu/ 를 이용하여 테스트하여야 한다.

[CoffeeScript] undefined를 void 0로 compile하는 이유는 무엇일까

 요새 재미삼아 만들고 있는 웹 프로그램이 있다.  JavaScript를 약간 하드하게 사용하여야 하므로, pure한 JavaScript를 사용하지 않고, CoffeeScript를 이용하여 개발을 진행하고 있다.  CoffeeScript 자체를 실행시키는 interpreter가 존재하지 않고, 언제나 JavaScript로 compile한 뒤 실행되어야 해서, 빠르게 코드 수정 내용을 테스트할 수 있다는 장점이 사라진다. 변환되는 과정에서 어떤 경우는 JavaScript로 직접 작성한 코드보다 비효율적인 코드가 나오기도 한다.  게다가 CoffeeScript는 기본적으로 모든 JavaScript 코드는 CoffeeScript 코드로, CoffeeScript 코드는 JavaScript 코드로 1:1로 변환 가능하게 해주는 것을 목표로 삼고 있기 때문에, JavaScript보다 더 powerful한 것도 아니다.  그럼에도 새 프로젝트에 JavaScript를 사용하지 않고 CoffeeScript를 사용하는 것은 다음의 두 가지 이유 때문이다.  우선 내가 c-style의 코드보다 ruby-style의 코드를 더 좋아한다.  별거 아니지만 오랜 시간 아무런 이득도 없이(쉽게 말해서 돈 받는 게 아니면서)  혼자서 쓸쓸히  작업하려면 내가 좋아하는 방식으로 작업하는 게 최고다.  다음으로 compile과정을 거치기 때문에 실수를 한번 걸러줄 수 있다. compile 과정에서 엄격한 정적 분석을 거치는 것은 아니지만, 기본적인 실수를 막아주는 역할 정도는 할 수 있다.   CoffeeScript가 undefined를 void 0로 compile하는 이유도 여기에 있다.  위와 같이 undefined를 사용하는 CoffeeScript 코드를 컴파일하면, 아래와 같이 undefined를 void 0로 변환한 JavaScript 코드를 돌려준다.  void 함수는 분명히 언제나 undefined를 return 하기는 하지만 굳이 멀쩡한 undefin

RAII는 무엇인가

  RAII 는 C++에서 자주 쓰이는 idiom으로 자원의 안전한 사용을 위해 객체가 쓰이는 스코프를 벗어나면 자원을 해제해주는 기법이다. C++에서 heap에 할당된 자원은 명시적으로 해제하지 않으면 해제되지 않지만, stack에 할당된 자원은 자신의 scope가 끝나면 메모리가 해제되며 destructor가 불린다는 원리를 이용한 것이다.  원래는 exception 등으로 control flow가 예상치 못하게 변경될 때를 대비하기 위해서 쓰이던 기법이다.  아래의 예제를 보자.  첫 번째 코드는 위험하다. thisFunctionCanThrowException() 함수에서 exception을 발생시킨다면 resource를 해제하지 못한다. 두 번째 코드는 일단은 resource를 해제하고 있다. 하지만 보기에 좋은 코드는 아니다. 그리고 유지하기도 어려워진다. 세 번째 코드는 RAII를 위해 c++ 11의 스마트 포인터인 unique_ptr을 이용하는 방법이다. unique_ptr은 소멸할 때 자신이 들고 있는 메모리를 해제시켜주기 때문에 함수 밖으로 나가면 resource가 해제되는 것이 보장된다.  여기서 말하는 자원은 단순히 heap 메모리만을 말하는 것이 아니다. heap 메모리 이외에도 파일이나 db와 같은 것들도 전부 RAII를 이용해 안전하게 사용할 수 있다. 여기에 더 나아가서 특정 scope를 벗어나면 반드시 실행돼야 하는 코드들도 RAII를 이용해 처리할 수 있다. 즉, 다른 언어에서 finally에 해당하는 구문을 RAII를 이용해서 처리할 수 있다. 실제로 C++의 아버지이자 RAII라는 용어를 처음 만든 Bjarne Stroustrub는 c++에 finally를 집어넣지 않는 이유를  "RAII가 있는데 굳이 있을 필요가 없다." 라고 말하고 있다.

잘못된 assert는 사용하지 말자

 assert라는 함수는 인자로 받는 조건이 true가 아니면 예외를 발생시키는 함수로, 디버깅을 도와주거나, 코드의 가독성을 올리는 용도로 쓰인다. 게다가 릴리즈에서는 아무 일도 않기 때문에(c++의 경우 NDEBUG가 정의되었는가 아닌가로 동작이 달라진다.), 성능 저하 없이 검증 코드를 집어넣을 수 있다.  근데 릴리즈에서는 아무 동작도 하지 않는다는 특성 때문인지, assert가 가지는 implicit 한 의미를 이해 못 했는지 assert를 잘못 사용하는 때도 있다.  다음의 코드를 보고 이상한 점을 찾아보자.  Connection이라는 class의 Send method에서 message를 받아서 platformConnection_(내부 구현이 어떻게 되었을지는 신경 쓰지 말자.)을 통해서 Send해주고 결과 값을 돌려준다. 그 전에 platformConnection_이 valid한지를 검사하여 valid하지 않다면 false를 돌려주는 평범한 코드다.  문제는 함수의 맨 앞에서 valid한지 아닌지 assert로 체크를 하고 있다는 것이다.  이 assert문이 가지는 의미는 절대로 valid하지 않을 때는 절대로 이 함수가 호출되지 않는다는 것이다. 그럼에도 그다음 문장에서 valid한지 않은지 검사하고 있다.  이에 대해 assert는 릴리즈 빌드에는 포함되지 않기 때문에 릴리즈 빌드를 위해서 안전한 코드를 작성해야 한다고 주장하는 사람도 있다. 하지만 이런 경우라면 애초에 assert를 쓰지 않고 조건문만을 써야 한다.  assert를 썼다면 assert에 걸릴만한 조건이 들어오지 않도록 코드를 작성했어야 한다.