Membase Server as Memcached

Membase Server를 memcached 대신 쓰기로 했다. Membase Server는 memcached 호환 프로토콜을 사용하기 때문에 memcached를 가정하고 만든 애플리케이션을 고치지 않고도 적용할 수 있다. 사용하려는 환경은 Ubuntu이므로 .deb 바이너리를 내려받는다. (커뮤니티 에디션 다운로드)

$ wget http://packages.couchbase.com/releases/1.7.1.1/membase-server-community_x86_64_1.7.1.1.deb

설치할 때는 의존성도 함께 설치해준다.

$ sudo dpkg -i membase-server-community_x86_64_1.7.1.1.deb 
$ sudo apt-get -f install

Membase Server는 기본적으로 상용 제품이기 때문에 매우 훌륭한 프론트엔드 콘솔을 제공한다. 설치하고 나서 8091 포트를 웹 브라우저로 접속해보면 설정을 진행할 수 있다.

Membase Console

다만 설정을 이런 식으로 해야 하면 디플로이 자동화가 문제인데, 저 프론트엔드는 JavaScript로 구현되어 있고 실제 설정 자체는 REST API로 제공된다. 일단 대충 둘러보는 용도로는 웹 브라우저에서 프론트엔드 콘솔을 사용하는게 편할 것이다.

Membase Configure: Step 1/4

자료를 저장할 파일시스템 상의 경로를 정한 뒤에 이미 존재하는 클러스터에 합류시킬 것인지 아니면 새로운 클러스터를 구성할 것인지 결정할 수 있다. 존재하는 클러스터가 없으므로 일단 만들어야 한다. 만약 클러스터에 합류하려고 한다면 클러스터 마스터의 IP 주소와 로그인 정보를 넣어야 한다.

Membase Configure: Step 2/4

그 뒤에 버킷 종류를 정해야 하는데 memcached와 Membase 둘이 있다. 짐작할 수 있다시피 둘의 차이는 영속성이다. memcached에 저장되는 자료는 휘발되어도 상관 없으므로 다중화(replication) 설정이 생략된다.

Membase Configure: Step 3/4

세번째로 나오는 화면에는 별거 없다. 적당히 채우고 진행한다.

Membase Configure: Step 4/4

마지막으로 클러스터 마스터의 관리자 계정을 만든다. 나중에 클러스터에 참여시킬 다른 노드에서 사용하게 된다.

여기까지 웹 프론트엔드 콘솔을 통해 설정한 내용은 사실 REST API로도 할 수 있다.

$ curl -d username=Administrator -d password=passsword -d port=SAME \
       http://localhost:8091/settings/web
$ curl -u Administrator:password \
       -d path=/opt/membase/var/lib/membase/data \
       http://localhost:8091/nodes/self/controller/settings
$ curl -u Administrator:password -d memoryQuota=1024 \
       http://localhost:8091/pools/default
$ curl -u Administrator:password \
       -d bucketType=memcached -d ramQuotaMB=1024 -d replicaNumber=2 \
       http://localhost:8091/controller/setupDefaultBucket
$ curl -u Administrator:password -d sendStats=true \
       http://localhost:8091/settings/stats

클러스터 마스터 노드를 설정한 뒤에는 나머지 노드를 클러스터에 붙일 수 있다. 이 역시 웹 프론트엔드 콘솔에서 설정 가능하고 UI만 따라가면 마술처럼 잘 된다. REST API로는 이런 식으로 한다.

$ curl -d path=/opt/membase/var/lib/membase/data \
       http://localhost:8091/nodes/self/controller/settings
$ curl -d clusterMemberHostIp=master-node-host -d clusterMemberPort=8091 \
       -d user=Administrator -d password=password \
       http://localhost:8091/node/controller/doJoinCluster

만약 붙어있던 노드가 어떤 이유로든 장애가 발생하면 어떻게 해야 할까? 클러스터에서 빼야 한다. 이걸 자동으로 빼주게 하려면 타임아웃을 설정하여 자동 failover시키면 된다.

$ curl -u Administrator:password -d enabled=true&timeout=60 \
       http://localhost:8091/settings/autoFailover

일단 이렇게 클러스터가 구성된 뒤에는, 애플리케이션 쪽에서 클러스터의 어떤 노드를 연결하더라도 클러스터 전체의 스토리지를 하나의 단일 스토리지처럼 투명하게 다룰 수 있게 된다.

사실 memcached로도 여러 노드를 다룰 수 있지만 기본적으로 클라이언트 쪽에서 모든 것을 다 처리해야 하기 때문에 관리가 쉽지 않다. 노드 한둘에 장애가 날 때마다 전체 노드 목록을 모든 애플리케이션 노드에 업데이트해야 하는데, 이렇게 되면 당연히 디플로이가 복잡해진다. 구현하더라도 failover가 완료되기 전까지 모든 애플리케이션에서는 장애가 난 memcached 노드를 밟을 때마다 삐걱거리며 에러 로그가 잔뜩 쌓이게 된다. 게다가 분산 책임이 클라이언트에 있으므로 전체 memcached 노드 목록이 달라질 때마다 키의 해시가 달라져서 전체 캐시가 리셋되는 현상을 방지하려면 consistent hashing 도입해야 하는데… 이쯤 되면 “심플해서” 선택했던 memcached에게 심플함은 전혀 남지 않고 관리 비용이 급속히 커진다.

만약 우리처럼

  • 애플리케이션이 memcached를 이미 사용하고 있고 (Membase Server는 memcached 호환 프로토콜을 구현한다)
  • 여러 애플리케이션 노드가 존재하고
  • 여러 memcached 노드가 존재하는

구성인 곳이라면 이미 memcached 관리에 스트레스를 꽤나 받고 있을테니 Membase Server를 memcached 대신 써보길 권하고 싶다.

2 months ago

누가 퍼뜨린 얘기인지는 모르겠지만, 가만 보면 사람들은 무엇에 대해 설명을 잘 하지 못하고 어렵게 말하는 것을 그 자신도 제대로 이해하지 못해서라고 굳게 믿는 것 같다. 하지만 골똘히 생각해보면 자신이 무엇을 이해하는 것과 그것을 말로 잘 표현해서 전달하는 것은 전혀 다른 종류의 능력이다. 그렇지 않다면 세상 모든 교수들과 전문가들이 Steve Jobs만큼 발표를 잘할 것이고 인기 소설가들처럼 그것을 잘 전달할 수 있었을 것이다. 양자역학을 일반인들에게 쉽게 설명할 능력이 없다고 해서 결코 모든 물리학자들의 양자역학에 대한 이해가 떨어진다고 볼 수는 없을 것이다.

반대로 생각해보자. 불교 선종(禪宗)에서는 불립문자(不立文字)라 하였다. 높은 수준의 이해는 말로 전할 수 없다. 스스로 궁리하여 깨달아야 한다. 본인의 노력 없이는 다른 사람으로부터 거저 얻을 수 없는 것이다.

물론 이해도가 높다면 좀더 쉽게 설명하는 방법을 찾기 쉽겠지만, 이해도가 높은 것과 그것을 잘 설명하는 것은 별개의 능력인 것은 확실한데, 왜 사람들은 설명을 잘하는 것이 높은 수준의 이해를 엿볼수 있는 것이며 설명을 잘 못하는 것이 이해를 잘 못하고 있는 것이라고 단정하는지 모르겠다.

2 months ago

AWS 한국 사용자 모임

…같은 건 없고, 그냥 비공식이지만 한국에서 Amazon Web Services 쓰는 사람들끼리 정보 공유를 하자는 의미로 IRC 채널을 작게 만들었다. (내가 만든 건 아니고 kkung 님이 시작.) 오징어 네트워크의 #aws 채널이다.

irc://irc.ozinger.org/aws
2 months ago

신생 언어 홍보 아이디어

밤 늦게 불현듯 떠오른 아이디어. IRC 봇 프레임워크를 아주 사용하기 좋게 만든 다음 Google App Engine처럼 PaaS로 제공하면 어떨까? 대신 그 프레임워크는 홍보하려는 언어로 만들어져 있고, 해당 PaaS에 자신이 원하는 봇을 올려서 운영하려면, 그 봇을 해당 언어로 스크립팅해야 한다.

미션 크리티컬한 서비스의 경우 이렇게 하면 PaaS가 망하겠지만, IRC 봇은 대부분 있으면 재밌고 좋지만 없어도 그만인 물건이기 때문에 오히려 직접 호스팅하는 쪽이 번거롭도 신경도 쓰이게 된다. 그런 것들을 그냥 PaaS에 올려서 디플로이도 쉽고 라이브에서 디버깅도 쉽게 해주면 각자 채널에서 소규모로 특수 목적 봇을 만드는 비용을 낮춰주기 때문에 많이 쓰이지 않을까? 설사 생소한 언어로 스크립팅해야 한다고 하더라도 하찮은 IRC 봇 하나 만드는데 관리 비용이 지속적으로 나가는 것보다는 낫기 때문에 쓸 동기가 충분할 것이라고 생각한다. 게다가 언어가 매우 편하면서 강력하고1PaaS 위에서 쓸 수 있는 IRC 봇 제작 프레임워크 역시 훌륭하다면 더욱 그렇다.

물론 이걸로 홍보하고자 하는 언어를 세상에 널리 알리기는 한참 부족하겠지만, 초기 사용자를 모으는 데는 꽤 괜찮지 않을까 싶다. IRC 봇은 그냥 한 가지 아이디어일 뿐이고, IRC 봇처럼 잉여한 것이라면 뭐든 PaaS로 홍보할 수 있지 않을까 싶다.

뭐, 이런 저런 소리를 길게 쓰긴 했지만, 새로운 생각이라고 생각하진 않는다. 이미 10년 전에 Paul Graham이 Being Popular라는 글을 쓴 적 있는 바, 내가 쓴 내용은 그 글의 응용 중 하나일 따름이다.


  1. 뭐, 농담 반 진담 반으로 하는 소리지만, 불편하고 기능이 부족한 언어는 널리 퍼지지 않고 일찌감치 망하는 편이 세상을 위해 이롭다. ㅋㅋ 사실 Google 공동 창업자 Larry Page도 사업 초창기에 마케팅 담당한테 “우리의 검색 품질이 좋지 않다면, 우리는 (세상을 위해서) 승리해서는 안된다”고 얘기했다고 한다. 

2 months ago

Celery + Amazon SQS 실패기

StyleShare1에서는 우선순위 큐(priority queue)가 필요해서 초기에 Celery를 쓰지 않고 직접 구현한 큐와 워커를 사용했다. 하지만 큐의 안정성이 떨어져서 우선순위 기능을 포기하고 RabbitMQ와 Celery를 쓰기로 결정했다.

사실 처음에는 Celery와 Amazon SQS를 쓸 예정이었다. StyleShare 인프라는 현재 Amazon Web Services 위에 구축되어 있고, AWS에 해당 용도의 서비스가 존재한다면 그걸 우선적으로 쓰는 걸 고려하고 있다. 예를 들어 우리는 L4를 직접 구축할 생각을 버리고 ELB를 쓰고 있고, 3개월 정도 지난 현재, 결과적으로는 좋은 선택이었다. 그런 의미에서 큐 역시 직접 구현하지 않고 SQS를 사용하는 쪽을 먼저 고려했던 것이다.

하지만 Celery의 SQS 지원은 현재 좋지 않았다. Celery가 의존하는 AMQP 메세징 라이브러리인 Kombu는 Celery 작성자가 직접 만든 물건인데 AMQP만 구현하는 것 뿐만 아니라 가상 트랜스포트(virtual transport)라는 개념으로 RDBMS나 Redis 등으로 AMQP의 기본적인 기능들을 에뮬레이션해서 똑같은 인터페이스로 사용할 수 있게 해준다. 따라서 Kombu 덕분에 Celery를 쓰게 되면 실제 서버에서는 RabbitMQ를 쓰면서, 로컬 개발 환경에서는 별도의 데몬을 돌리는 대신 간편하게 SQLite를 큐처럼 쓸 수 있는 것이다. 비효율적이고 안정적이지 못하지만 개발 환경을 간소화하는 데는 무척 도움이 된다. 이와 마찬가지로 SQS 역시 Kombu에서 같은 인터페이스로 다룰 수 있게 되어 있긴 하다. 하지만 몇가지 문제가 있어서 패치가 필요한데, 내가 제출한 패치이 시각까지는 아직 업스트림에 합쳐지지 못했다 이제 업스트림에 반영되었다.

가까스로 문제를 해결하여 커넥션까지 성공했다. 하지만 생각처럼 매끄럽게 돌아가지는 않았다. 일단 큐에 던지는 것은 문제 없이 되었다. 하지만 SQS에 메세지가 몇십만개 쌓이도록 워커는 늑장을 부리는게 아닌가. SQS 자체는 안정적이긴 했으나 RabbitMQ만큼 날쌔다는 느낌은 없었다. 게다가 Kombu의 SQS 지원이 미흡하여 커넥션이 오래될수록 큐에서 새로운 메세지를 받는 것이 느려졌다. 아직도 원인은 정확히 파악하지 못했다.

그래서 도중에 방향을 바꾸고 RabbitMQ를 직접 설치해서 운영하기로 했다. 명성대로 잘 동작해주었고, 애초에 Celery는 RabbitMQ를 최우선 백엔드로 지원하고 있기 때문에 궁합도 완벽했다. SQS를 쓸 때처럼 내가 패치를 해줘야 하는 부분은 단 하나도 없었고 시도한지 3시간 안에 모든 전환을 마칠 수 있었다.

내 생각에는 SQS 자체의 문제라기 보다는 Kombu의 SQS 지원 미흡이 가장 큰 실패 요인이었다고 생각한다. 차라리 이쪽 부분은 AWS 직원들 중 SQS 개발하는 쪽에서 시간이 날때 패치를 제출하면 모든 문제가 ‘올바르게’ 풀릴 것 같은데, 실무에서 적용하는 입장에서는 시간을 내서 패치를 직접 했음에도 불구하고 매끄럽게 돌아가지 않는다면 굳이 안되는 걸 고집하고 씨름할 수 없기 때문에 결국 RabbitMQ를 쓰게 되었다.

만약 Celery를 SQS 백엔드로 쓰고 싶은 사람이 있다면 아직은 말리고 싶다. 꼭 SQS를 특별히 얘기하는 것은 아니고, Celery와 Kombu 자체가 아직까지 RabbitMQ 중심으로 구현되어 있기 때문이다. 다중 백엔드를 지원하기 위해 인터페이스가 잘 디자인되어 있긴 하지만, 실제로 사용되는 구현만이 버그도 많이 밟혀서 안정적으로 될 수밖에 없는 것이다. 따라서 아직은 RabbitMQ 말고는 추천할 만한 백엔드가 없다. AMQP 구현체 다른 것도 상황은 마찬가지다. Celery에서는 아직 RabbitMQ만 안심하고 쓸 수 있다.


  1. 생각해보니 블로그에서는 처음 말하는 것 같은데, 나는 올해 초부터 StyleShare라는 스타트업을 하고 있다. 패션 소셜 네트워크 서비스라고 생각하면 된다. 

2 months ago