Tumblr의 아키텍처와 그들의 기업 문화에 대해 정리한걸 공유합니다. Tumblr가 어떻게 1억 PV를 서비스하기 위해 노력한 결과물을 우리가 살펴봄으로써 우리가 만들고자하는 서비스가 트래픽이 증가했을때 Scale Out에 대한 고민을 조금이나마 도와줄 수 있는 토대가 되면 좋겠습니다.
서비스 규모
- Tumblr CEO : David Karp.
- 오픈 일자 : 2007년 4월 27일.
- 총 블로그 수 : 6천 9백 4십만개.(2012.8.20 기준)
- 게시물 수 : 2백9십8억개.(2012.8.20 기준)
- 일 포스팅 수 : 7천1백6십만개.(2012.7 기준)
- 일 페이지뷰는 500,000,000.
- 트래픽은 피크시 40,000 RPS.
- 매일 1TB 데이터가 하둡 클러스터에 저장됨.
- MySQL/HBase/Redis/Memcache에 매일 수 TB의 데이터가 쌓임.
- 포스트는 매일 50GB, 팔로어 리스트 업데이트가 하루에 2.7TB정도 일어남.
- 서비스 성장률이 월 30%이상이고, 위의 서비스 규모와 1000대의 서버를 엔지니어 20명이 관리하고 있다.
아키텍처
1. 특징
-
Tumblr는 다른 소셜 네트워크와는 이용 패턴이 다르다.
- 하루에 5천만의 게시물이 등록되고, 평균적으로 게시물에 수백의 사용자들이 방문한다. 그리고 단지 한,두 사용자에게서만 수백만의 팔로어를 가지는 것은 아니다. Tumblr 사용자들의 그래프를 보면 수백의 팔로어를 가지고 있다. follower가 많은 사용자, 포스팅이 많은 사용자가 대시보드에 디스플레이 되어야 하기 때문에 Tumblr의 스케일은 어렵다. 이런 것이 다른 소셜 네트워크와 다른 점이다.
- 소셜네트워크의 체류시간 관점에서 보면 흥미롭다. 게시물은 바이트 사이즈로만 이루어진 것이 아니며, 이미지와 동영상도 있다. 긴 형식은 아니지만, 글에는 솜씨를 가지고 있어 사람들은 긴(한) 시간 체류할 수 있을 정도의 가치를 가진 깊이있는 콘텐츠를 쓴다.
- 사용자들은 다른 사용자들과 연결을 형성하며, 그들은 콘텐츠를 읽기 위해 대시보드의 수백 페이지를 재방문한다. 다른 소셜 네트워크는 단지 스트림 방식이어서 한번 읽고 만다.
- 사용자의 수, 사용자들의 평균 도달 범위, 사용자의 높은 게시 활동이 주는 함축적 의미는 엄청난 양의 데이터 업데이트가 일어난다는 것이다.
- Tumblr는 하나의 코로케이션(동일 지역) 사이트내에서 구동된다. 미래를 위해 지리적 분포도 설계에 고려해야 한다.
-
플랫폼으로서 Tumblr는 두개의 콤포넌트(Tumblelogs, Dashboard)를 가지고 있다.
- 인터넷에 공개되어 있는 Tumblelog는 캐싱되어 있다.
- Dashboard는 트위터의 타임라인과 비슷하며 그들이 팔로우한 사용자들의 데이터를 실시간으로 업데이트해야 한다. 블로그와는 다른 스케일의 특징중에 하나다. 매 요청때마다 데이터가 다르기 때문에 특히나 액티브 사용자의 경우 캐싱이 유용하지 않을 수 있다. 그리고 실시간성과 일관성도 필요하다. 즉, 삭제된 포스트는 보여주지 말아야 한다. 그리고 많은 데이터가 처리되고 있고 게시물은 하루에 50G가 발생하고 팔로어 리스트는 하루에 2.7TB가 업데이트 된다. 미디어 데이터는 모두 S3에 저장된다.
- 대부분의 사용자는 콘텐츠 소비를 위한 도구로 텀블러를 활용한다. 하루 5억 PV중 70%가 대시보드에서 발생한다.
- Dashboard의 가용성은 좋지만, Tumblelog는 마이그레이션 하기 어려운 인프라 구조를 가지고 있어서 가용성이 좋지 않다. 작은 팀이 스케일 이슈가 무엇인지, 해결방안은 뭔지 선택하고 해결해야 했다.
2. 과거의 Tumblr
- 최초에는 Rackspace 환경에서 독자 도메인 블로그에 콘텐츠를 기록했었는데, 2007년까지 데이터가 크게 증가해 데이터 센터를 확장할 때 사용자가 너무 많아서 마이그레이션이 힘들었다. 지금도 Rackspace상에서 독자 도메인을 가지고 있다. 그들은 HAProxy나 Varnish를 사용하여 새로운 데이터 센터의 Rackspace로 라우팅 시킨다. 기존 레거시 이슈는 아래와 같다.
-
전통적인 LAMP로 진행했던 상황을 정리하면.
- 지금까지 PHP로만 개발해왔고, 대부분 엔지니어가 PHP개발자다.
- 웹서버, DB서버, PHP 애플리케이션과 함께 시작하게 되었다.
- 스케일을 위해 memcache를 사용하기 시작했고, 앞단에 cache를 두었고, cache앞에는 HAProxy를 놓았고, MySQL sharding도 두어 상당히 도움이 많이 됐다.
- 싱글 서버 방식으로 모든 시스템을 구성했다. 백엔드는 이중화방식으로 C로 개발했고(ID generator, Staircar), Dashboard 노티를 위해 Redis를 이용했다.
- Dashboard는 scatter-gather(저장은 분산, 뷰잉은 모아서) 모델로 만들어져 있다. 이 방식은 사용자가 대시보드에 액세스했을 때 이벤트가 발생된다. 자신이 팔로잉한 사용자의 이벤트를 끌어 모아서 표시한다. 이 모델은 6개월정도만 스케일 되는 한계가 있다. 그리고 데이터는 시간 순서로 샤딩 스키마에 저장되고 특별한 경우 잘 동작 안할 수 있다.
3. 새로운 Tumblr
- 개발과 채용 속도를 위해서 JVM 중심으로 이동하고 있다.
- 목표는 서비스내에 있는 PHP 응용 프로그램 밖으로 모든것을 이동시키는 것이다. PHP를 서비스 위에서 Thin 레이어로 앱을 만들고 인증과 뷰 요청을 처리한다.
-
Scala와 Finagle(Twitter에서 개발한 RPC용 네트워크 스택)을 채택했다.
- 직원들은 모두 Ruby와 PHP의 경험이 있었기 때문에, Scala는 상당히 매력적이었다.
- Finagle이 Scala를 선택하게 된 중요한 이유였다. Twitter가 개발 한 라이브러리로 분산 시스템의 대부분의 이슈, 분산 추적 및 서비스의 검색, 등록 등을 해 준다. 이러한 것을 직접 구현할 필요 없이 무료로 사용할 수 있었다.
- Finagle이 우리가 필요한 모든(Thrift, ZooKeeper 등) 기반 기능들을 제공해 주었다.
- Finagle은 Foursqure와 Twitter에서, Scala는 Meetup에서 사용되고 있다.
- Thrift 애플리케이션 인터페이스는 좋다. 매우 훌륭한 성능도 갖추고 있다.
- Netty도 좋지만, Java는 사용하고 싶지 않았다. 그래서 Scala가 좋은 대안이 되었다.
- Finagle을 선택한 이유는 자체의 멋진 점도 있고, 개발자들 사이에 아는 사람도 몇몇 있었고, 많은 네트워크 코드 필요 없었고, 분산 환경에서 필요한 것은 다 해주었다.
- Node.js는 JVM을 팀에 확산하는게 쉬워서 선택하지 않았다. Node.js는 아직 개발이 충분히 되지 않았고, 표준 및 모범 사례, 좋은 테스트 코드도 많이 없다. Scala라면, Java 코드를 사용할 수 있다. Node.js는 확장에 필요한 사용 방법에 대한 지식이 아직 많이 없었고, 5ms 응답 시간, 99.99%의 가용성, 초당 4만에서 40만 요청을 실현하는데에 별로 아는 지식이 없었다. Tumblr에서 목표로 한 것들이 Java 에코 시스템에서는 가능하다는 결론에 도달했다.
- C/libevent기반의 내부 서비스는 Scala/Finagle 기반으로 전환됐다.
- HBase와 Redis 같은 NoSQL도 사용하고 있지만, 원본 데이터는 파티셔닝된 MySQL 에 넣고 있고, HBase로 대체 생각은 없다.
- HBase는 수십억의 단축 URL이나 히스토리 데이터, 그리고 분석 용도의 백업으로 사용하고 있다. HBase는 대시보드 교체를 위해 초당 수백만의 쓰기 성능이 발생하는 곳에서 사용중이다. 그들이 가진 사용자를 Hbase상에서 비즈니스를 배팅할 수 없기 때문에 HBase를 MySQL대신으로 할 순 없다. 단지 경험을 얻기 위해서 위험이 적은 곳에서 사용하고 있다.
- MySQL에서(데이터 시간을 키로 한) sharding의 문제점은 특정 shard에만 액세스가 집중하는 것이다. 그리고 리플리케이션 환경에서 동시 쓰기작업이 많이 이루어지기 때문에 슬레이브에서 읽기 지연이 발생한다.
-
공통의 서비스 프레임워크를 만들었다.
- 분산 시스템을 관리하는 방법에 대한 운영 문제를 선해결하는데 많은 시간을 보냈다.
- 일종의 Rails scaffolding(Rails의 MVC 코드 자동 생성 도구)을 서비스용으로 구축했다. 그 탬플릿은 내부적으로 부트스트랩 서비스용에 사용된다.
- 모든 서비스들은 일관된 운영 방안을 가지고 있다. 통계 확인, 모니터링, 모든 작업은 동일한 방식으로 시작하고 중지한다.
- 툴은 저장소에 퍼블리싱하거나, Git에 태깅하는 일과 같은 공통의 활동들을 처리해주는 헬퍼나 플리그인을 통해서 SBT(Scala build tool)내에 빌드 프로세스로 들어가게 된다. 대부분의 개발자들은 빌드 시스템 내에 들어갈 필요가 없다.
- Front-end layer는 HAProxy를 사용하고 Varnish는 공개 블로그의 히트용으로 사용된다. 전체 40개의 장비에 설치되어 있다.
- 500대의 웹 서버는 Apache와 PHP 애플리케이션이 구동중이다.
- 200대의 데이터베이스 서버가 있고, 많은 데이터 베이스 서버는 고가용성을 위해 사용된다. 하드웨어 제품은 MTBF가 놀라울 정도로 낮은 것을 사용한다. 장애에 대비해 많은 수의 여분의 하드웨어가 있다.
- 6개의 백엔드 서비스에 PHP 애플리케이션이 지원하고 있고, 하나의 팀은 백엔드 서비스 개발에 최선을 다하고 있다. 새로운 서비스는 2~3주안에 나오고 대시보드 노티나 대시보드 보조 인덱스, 단축 URL, 그리고 투명하게 샤딩을 처리할 수 있는 Memcache 프록시를 제공하고 있다.
- MySQL의 sharding에 많은 시간과 노력과 도구를 투입하고 있다. MongoDB는 NY(자신의 위치)에 인기가 있을지언정 사용하지 않는다. MySQL이 스케일에 좋다.
- Gearman은 잡용 큐 시스템으로 사람의 개입없이 장기적으로, 정기적으로 잡을 실행시키는데 사용된다.
- 가용성은 도달 범위의 관점에서 측정된다. 즉, 사용자는 대시보드나 고객 도메인에 도달할 수 있나?라는 관점. 에러율 관점도 같다.
- 히스토리에 의해 가장 우선순위가 높은 아이템이 고정된다. 실패(장애) 모드들은 분석되고 체계적으로 관리되어진다. 의도는 사용자 관점과 애플리케이션 관점에서 성공 여부를 측정하는 것이다.
- 초기 Actor 모델에서 Finagle(Twitter에서 개발한 RPC용 네트워크 스택)을 사용했지만, 지금은 드랍했다.
- Scala는 상태를 공유하는 시스템에는 권장하지 않는다. Finagle은 트위터에서 테스트 되었기 때문에 괜찮다고 가정했다. 가변적인 상태는 스칼라나 Finagle에서 constructs를 사용해서 피할 수 있다. 긴 실행 상태의 서버에는 사용하지 않는다. 상태는 DB로부터 오고 해당 데이터 베이스로 N만큼 재작성된다. 잇점은 개발자가 쓰레드나 잠금에 대해서 걱정할 필요가 없다는 것이다.
-
22개의 Redis 서버. 각 서버는 8-23 인스턴스들을 가지고 있고 Redis의 인스턴스는 총 100개로 상용에서 운영중이다.
- Redis는 대시보드의 노티(like 등)를 위해 백엔드 스토리지용으로 사용된다.
- 높은 쓰기 비율은 MySQL의 대안으로 적합하다.
- Redis 인터페이스 기반은 스칼라로 되어 있고 셀 아키텍처로 이전중이다.
- 단축 URL은 Redis를 캐시로 사용하고 있고, HBase를 데이터의 영구 저장소로 활용하고 있다.
- 대시보드의 보조 인덱스로 Redis를 활용하고 있다.
4. Internal Firehose
Internal Firehose의 역할은 사용자의 포스트(게시물)를 저장해 놓고 그 게시물을 비동기적으로 각 셀에 게시물 내용을 분산 저장시키는 역할을 한다. 자세한 내용은 아래와 같다.
- 내부 애플리케이션들은 액티비티 스트림에 액서스가 필요하며 액티비티 스트림은 사용자가 글의 포스팅과 삭제, 링크와 언링크 등에 관한 정보이다. Tumblr 아키텍처의 한가지 도전 과제는 실시간으로 많은 데이터를 셀에 분산시키는 일이다. 우리가 원하는 것중에 하나가 내부의 스케일 확장과 애플리케이션 에코시스템이 안정적으로 성장시키는 것이었다. 결국, 분산의 중심 기점이 필요했던 것이다.
- 예전에 이들 정보는 Scribe/Hadoop을 통해 배포를 했었다. 서비스들은 Scribe에 로그를 쌓았고 Tail을 해 파이프형태로 앱의 데이터를 관리했다. 이 모델은 특히 게시물이 특히 피크치인 초당 1000개가 발생되면 스케일링이 멈춰버린다. 그리고 사람들은 파일을 테일링하고 내용을 긁어 파이프라인 형태로 하는 것을 원치 않았다.
- 그래서 내부 firebose라는 메세지 버스가 많들어졌다. 서비스와 애플리케이션들은 Thrift를 통해 Firehose와 통신을 했다.
- Linkedin의 Kafka는 메세지를 저장하는데 사용된다. 내부적으로 콘텐츠 소비자는 Firehose로부터 데이터를 읽을때는 HTTP 스트림을 사용한다. MySQL은 샤딩의 구현이 자주 일어나는 관계로 거대한 데이터 스트림을 쓰는 것은 좋은 생각이 아닌거 같아서 MySQL을 사용하지는 않았다.
-
Tumblr의 Firehose 모델은 매우 유연하며, 일부 수정을 통해, 데이터가 손실될 수도 있는 트위터의 Firehose와는 다르게 했다.
- firehose 스트림은 필요할 때 되돌릴 수 있다. 이유는 데이터를 일주일 동안 유지를 하기 때문이다. 연결상에서 읽기 시작하는 시점을 지정할 수도 있다.
- 여러 클라이언트가 연결할 수 있으며 각 클라이언트는 중복된 데이터를 볼 수 없다. 각 클라이언트는 클라이언트 ID를 가지고 있다. Kafka는 소비 그룹 형태도 지원한다. 각 소비 그룹의 콘텐츠 소비자는 중복되지도 않으면서 자신의 메세지를 받을 수 있다. 여러 클라이언트는 동일한 소비자 ID를 생성할 수 있고, 이 때도 중복 데이터는 보이지 않는다. 이 데이터는 독립적이면서도 병렬적으로 처리된다. Kafka는 ZooKeeper를 사용해 콘텐츠 소비자가 얼마나 멀리 읽었는지를 정기적으로 체크포인트를 관리한다.
- Redis는 Finagle을 사용해 만들어진 memcached 프록시를 통해 Gearman 퍼시스턴시 레이어로 사용하고 있다.
- 조금씩 memcached에서 Redis로 이전중이다.
사용 기술
1. 소프트웨어 스택
- OS : Linux(CentOS)
- 웹서버 : Apache
- 언어 : PHP, Scala, Ruby
- RDB : MySQL(shard)
- NoSQL : Redis, HBase
- 로드발란싱 : Varnish, HA-Proxy, nginx
- 캐시 : Memcached
- RPC 프레임워크 : Finagle(Twitter에서 공개한 오픈 소스)
- 큐 : Gearman, Kafka(Linkedin에서 공개한 오픈 소스), Kestrel
- 배포/관리 도구 : Jenkins, Capistrano, Puppet
- 소스 관리 : Git
2. 인프라
- 웹서버 : 500대
- DB : 200대(47개는 pool, 30개는 shard)
- memcached 서버 : 30대
- redis 서버 : 22대
- varnish 서버 : 15대
- HAProxy : 25대
- nginx : 8대
- 큐서버(kestrel, gearman - Job 용) : 14대
Cell 기반 아키텍처
Tumblr에서 Cell 기반 아키텍처는 사용자 단위로 셀이 분할되며, 각 셀은 Hbase Cluster, Service Cluster, Redis Cache Cluster로 구성되어 있다. 그리고 사용자가 게시물을 올리면 Firehose가 받아서 비동기적으로 각 셀에 데이터를 분산 저장시킨다. 자세한 아키텍처의 내용은 아래와 같다.
-
Dashboard는 scatter-gather(분산되게 데이터를 저장하고 보여줄때는 모으는 방식) 모델로 만들어져 있어 운영에 한계가 있다.
- 그래서 해결책은 Inbox 모델로 전환하는 것이다. inbox모델은 페이스북 메세지와 비슷한 셀 기반의 아키텍처로 구성되어 있다.
- inbox는 scatter-gather 모델과 반대로 사용자의 대시보드는 타임순서로 한 셀에 같이 저장된다. 그 대시보드는 다른 사용자들의 게시물 이벤트(리블로그 등) 액션들과 팔로우 사용자가 올린 게시물로 구성되어 있다.
- inbox 구조로 했기 때문에 scatter-gather문제가 해결되었다. inbox를 통하면, 팔로우하고 있는 각 사용자에게 가는데에 비용이 많이 들지 않는다. 그리고 스케일 관점에서도 먼 미래를 내다 볼 수 있게 되었다.
-
대시보드에 재작성하는 것은 어려운 일이다. 데이터는 분산 특성을 가지고 있지만, 트랜젝션은 보장하고 있고 사용자가 부분 업데이트하는 것도 안된다.
- 데이터량이 어마어마하다. 페이스북과는 또다른 문제이다. 평균적으로 수백의 다른 사용자에게 메세지를 전달해야만 한다. 넓은 날짜 분포+ 높은 분산율 + 여러 데이터센터.
- 읽기가 초당 5만이고 쓰기가 초당 100만, 데이터셋 사이즈는 압축과 복제가 없이 2.7테라씩 증가한다. inbox안의 콘텐츠를 가르키는 24바이트의 로우키를 초당 100만의 쓰기가 이루어진다.
-
Cells
- 사용자의 대시보드를 표시하는데 필요한 모든 데이터가 한 셀에 들어있다.
- 사용자는 셀 속에 존재하고 데이터 센터마다 많은 셀이 존재한다.
- 셀은 HBase 클러스터, 서비스 클러스터, Redis 클러스트를 가지고 있다.
- 사용자들은 하나의 셀에 원 저장소를 갖고 firehose 업데이트를 통해 모든 게시물이 모든 셀에 카피된다.
- 각 셀은 Finagle(비동기) 기반이고 Thrift 위에 서비스 요청이나 firehose를 통해 HBase에 저장된다.
- 사용자가 대시보드를 방문하면 특정 홈셀의 사용자에 대해 하나의 서비스 노드는 HBase를 통해 자신의 대시보드를 읽는다. 그리고 읽은 데이터를 재전송한다.
- 백그라운드 잡은 요청을 처리하고 테이블에 저장하기 위해 firehose가 처리한다.
- Redis의 캐시 레이어는 한 셀안에 게시물들을 저장한다.
- 요청 흐름(작동 방식) : 사용자가 게시물을 퍼블리싱하고 그 게시물은 firehose에 저장된다. 그리고 모든 셀이 게시물 내용을 받고 데이터베이스에 게시물 내용을 저장한다. 셀은 게시물 작성자의 팔로어가 해당 셀에 있는지 확인한다. 만약 있다면 해당 팔로어의 inbox에 게시물 ID를 저장한다.
-
셀 기반 설계의 잇점
- 거대한 규모의 병렬화가 필요하며 별렬화 구성 콤포넌트간의 상호작용이 없도록 격리되어 있다. 셀은 사용자 기반으로 확장하므로 규모를 조절할 수 있는 병렬화 단위를 제공한다.
- 셀은 장애와도 격리되어 있다. 즉, 하나의 셀이 장애가 나도, 다른 셀에는 영향이 없다.
- 셀은 업그레이드 테스트 할 능력, 다양한 형태의 업그레이드 기능을 구현하는 능력, 소프트웨어의 다른 버전을 테스트 할 수 있는 능력과 같은 좋은 기능을 가지고 있다.
-
놓지기 쉬운 핵심 아이디어 : 모든 게시물은 모든 셀에 복제된다.
- 각각의 셀은 모든 게시물의 단일 복사본을 저장한다. 이렇게 함으로써 각각의 셀은 사용자의 대시보드 디스플레이 요청을 완벽하게 충족시켜준다. 애플리케이션은 모든 게시물 ID를 요청할 필요없이(Inbox에 있으니깐) 게시물을 디스플레이하기 위한 게시물 ID만 요청하면 된다. 그러면 각셀은 해당 사용자의 대시보드 콘텐츠를 리턴한다. 모든 셀은 셀간의 통신없이 자체 셀에서 대시보드에 필요한 모든 데이터를 가지고 있다.
- 셀마다 두개의 HBase 테이블이 사용된다. 한쪽에는 게시물 복사본이 들어있다. 그 데이터는 셀 내의 모든 사용자의 모든 게시물 ID를 저장하는 다른 테이블에 비해 작다. 두번째 테이블은 팔로잉하는 모든 사용자를 가져올 필요는 없다.
- 게시물의 사이즈가 너무 크기 때문에 inbox안에 직접 넣지 않고 ID만 받아서 inbox안에 저장한다. 게시물의 내용은 한번만 셀에 저장된다. 이 모델은 사용자 inbox에 타임순으로 게시물 ID만 저장되므로 스토리지 사용량이 절약된다. 단점으로는 게시물이 전체 셀에 모두 복사된다는 점이다. 놀랍게도 게시물은 inbox의 매핑량보다 작다. 게시물은 하루에 셀마다 50GB 정도 쌓이고 inbox는 하루에 2.7TB정도씩 누적된다. 사용자들은 생산보다는 오히려 소비를 한다.
- 사용자의 대시보드는 게시물의 텍스트를 포함하지 않고 단지 게시물 ID만, 증가의 대부분은 게시물 ID에 있다.
- 모든 게시물이 각 셀에 있기 때문에 팔로어가 디자인을 변경해도 괜찮다. 팔로어의 게시물이 하나의 셀에 저장이 되면 셀은 팔로어가 바뀌고 다시 채우고 정렬하는 것이 필요하게 되는데 이런 것이 필요없게 된다.
- 또 다른 디자인의 대안은 게시물의 텍스트를 저장하기 이해서 별도의 게시물 클러스터를 사용하는 것이다. 이 디자인의 단점은 클러스터가 다운되면 전체 사이트에 영향을 주게 된다. 모든 셀에 셀 설계와 게시물을 리플리케이션을 사용하면 매우 강력한 아키텍처가 된다.
아래는 개인적으로 생각해서 그린 Tumblr의 Cell 기반의 아키텍처이다.
Tumblr가 공개한 오픈 소스
Tumblr 개발 문화
1. 팀 조직
- 팀은 인프라, 플랫폼, SRE, 제품, 웹 운영, 서비스 팀으로 구성되어 있다.
- 인프라: 레이어 5이하, IP주소, DNS, 하드웨어 프로비저닝을 담당.
- 플랫폼: 핵심 앱 개발, SQL 샤딩, 서비스, 웹 운영.
- SRE: 서비스와 웹 운영팀 사이에서 신뢰성과 확장성 관점에서 요구 사항 분석에 집중하고 있음.
- 서비스 팀: 좀 더 전략적인 일에 집중하고 있으며, 전략은 2-3달 주기로 끝난다.
- 웹운영: 문제 감지, 대응, 튜닝을 책임지고 있다.
2. 소프트웨어 배포
- rsync 스크립트를 통해 PHP 애플리케이션을 분산 배포한다. 서버가 200개에 도달하면 문제가 발생하기 시작한다. 배포에는 오랜 걸렸고 서버들은 배포과정에서 다양한 상태들이 존재하게 된다.
- 다음 단계는 Capistrano(Ruby기반의 배포 도구)를 사용해 서비스 스택내에 배포 프로세스(개발, 스태이징, 생성)를 구축했다. 수 십대의 서버가 서비스를 작동시키지만, 수 백대의 서버에 배포하면 SSH 연결이 실패가 발생한다.
- 코디용 소프트웨어가 모든 서버에서 구동된다. 이거은 레드햇 Func(안전한 원격 제어 프레임워크) 기반의 가벼운 API들로 호스트에 커맨드를 보내는 방식으로 되어 있다. 스케일도 Func기반으로 되어 있다.
- 빌드 배포는 SSH를 피해 호스트 군에 X(Func 명령) 명령을 실행함으로써 끝난다. A그룹에 소프트웨어를 디플로이를 원한다면 마스터는 노드군(콘트롤 호스트군에 속한)을 식별해 배포 커맨드를 실행한다.
- 배포 커맨드는 Capistrano를 통해 구현되어 있다. 또한, git으로 체크아웃하고 Repository에서 받아올 수도 있다. HTTP 인터페이스로 연동되어 확장하기 쉽다. Capistrano는 PHP앱과 잘 동작하는 심플한 디렉토리 기반의 버전을 지원하기 때문에 좋다.버전 업데이트를 확인하려면 각 디렉토리가 SHA를 포함하고 있는 업데이트 버전으로 이동하면 된다.
- Func API는 서버들이 가지고 있는 소프트웨어 버전을 보고 상태를 재보고한다.
- 그들은 연결을 종료하고 다시 시작할 수 있기 때문에 안전하게 서비스 리스타트가 가능하다.
- 모든 기능들이 활성화되기 전에 다크 모드로 실행된다.
3. 개발 방식
- 누구든지 자신이 원하는 도구를 사용한다는 철학으로 시작하지만, 팀이 커지면 이 방식은 통하지 않게 된다. 새로온 직원은 처음에 매우 어렵게 느낀다. 그래서 새로운 직원이 더 좋은 팀으로 통합되기 위해서, 제품의 문제를 신속하게 해결하려면 스택의 표준화해야 한다. 그리고 운영룰을 구축해야 한다.
- 이 프로세스는 경량의 스크럼과 비슷하다.
- 모든 개발자는 개발 환경이 구성된 개발 머신이 주어지고 그 환경은 Puppet 자동으로 업데이트 된다.
- 개발 장비는 출시 후 변경, 테스트를 해 스테이징 장비로 이동할 수도 있고 상용 장비로 이동할 수도 있다.
- 개발자들은 vim과 Textmate를 사용한다.
- PHP 애플리케이션의 코드 리뷰가 테스트이다.
- 서비스측면에서 그들은 커밋이나 후킹, 젠킨스, CI, 노티와 함게 테스트 인프라를 구축한다.
4. 채용 프로세스
- 인터뷰는 보통 수학, 퍼즐, 어려운 문제들은 없다. 지원자가 실제 할수 있는 일에 초점을 맞춰 질문한다. 스마트합니까? 장기가 있나요? 그러나, GTD의 측정은 평가하기 어렵다. 목표는 사람들을 유지하는 것보다 좋은 사람들을 찾는것이다.
- 코딩에 집중한다. 샘플 코드를 요청하고 전화 인터뷰 동안 그들은 공유 코드를 작성하기 위한 공유에디터를 사용할 것이다. 즉, 코딩 테스트를 한다.
- 인터뷰에서는 대립하지 않고 단지 최고의 사람을 찾는다. 지원자는 인터뷰 동안 구글 검색과 같이 모든 도구를 사용하게 한다. 지원자가 면접에서 최상의 성능을 발휘하려면 평상시 사용하는 도구를 가지게 하는 것이 아이디어다.
- 도전은 텀블러 트래픽 수준에 준하는 스케일 경험을 가진 사람들을 찾는 것이다. 세계에서 몇 안되는 회사만이 이런 문제를 해결하기 위해 노력하고 있다.
Tumblr가 배운점
- 모든 영역을 자동화하자.
- MySQL(샤딩 포함)은 스케일하다. 하지만 앱은 그렇지 않다.
- Redis는 놀랍다.
- 스칼라도 환상적이다.
- 진행하고 있는 프로젝트 중 불확실한 것은 체크를 하자.
- 무모한 기술적 도전을 위해 사람들을 채용하지 마라. 팀에 부합하고 일을 할 수 있는 사람을 고용하자.
- 당신에게 필요한 사람을 고용하는데 도움을 줄 수 있는 스택을 선택하자.
- 우리 팀의 기술력을 높이자.
- 논문과 블로그를 읽자. 셀 아키텍처와 같은 핵심적인 설계 아이디어와 선택의 구체화는 나 아닌 다른 사람이 할 수도 있다.
- 동료에게 물어봐라. 페이스북, 링크드인, 트위터의 엔지니들의 경험에 관해 이야기해서 그들로부터 배웠다.
- 기술은 한 순간에 올라갈 수 없다. 제품 출시에 앞서 위험이 제한적 때, 파일럿 프로젝트 등에서 사용해 보고 익히는 연습을 하자.