Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
GOOZY
     В поисках идеальной архитектуры




2011, e-Legion ltd.               Юрий Буянов
 Goozyware inc.                     @digal
• Пара   слов о проекте

• Первая    версия и первые проблемы

• Новые    требования и новая архитектура

•В   самом низу

• Приключения     с хостингом

• Синяки    и шишки

• Looking   Forward
Юрий Буянов «Архитектура Goozy»
СПЕЦИФИКА

• Социальность: пользователь   хочет быть постоянно в курсе

 •2  req/min от каждого пользователя (даже когда он
   ничего не делает).

• Вездесущность: работает   на всех сайтах

 • Запрос   при открытии каждой страницы.
V.1
Portal Users               Client Users




                Django


               Memcached


                MySQL
ПЕРВАЯ НАГРУЗКА
ПЕРВАЯ НАГРУЗКА
ПЕРВАЯ НАГРУЗКА
ПОДРОБНЕЕ О НАГРУЗКЕ
   Portal Users               Client Users




                   Django


                  Memcached


                   MySQL
ПОДРОБНЕЕ О НАГРУЗКЕ
   Portal Users               Client Users




                   Django


                  Memcached


                   MySQL
LOAD TEST




• Пропускная   способность: 50 TPS

• Отклик: 2500   ms
НЕМНОГО ЧИСЕЛ


• 11   000 пользователей

• 1000   онлайн (в пике)

•2   сервера

• 500   мб данных
НЕМНОГО ЧИСЕЛ


• 11   000 пользователей   • 11   000 пользователей

• 1000   онлайн (в пике)   • 23   000 стикеров

•2   сервера               • 30   000 комментариев

• 500   мб данных          •2   200 000 таймлайн-записей
НОВЫЕ ТРЕБОВАНИЯ




    1 000 000
НОВЫЕ ТРЕБОВАНИЯ


•1 000 000 пользователей
•> 100 000 онлайн
•> 10 000 TPS
•> 50 Гб данных
•200 серверов
НОВЫЕ ТРЕБОВАНИЯ


•1 000 000 пользователей
•> 100 000 онлайн
•> 10 000 TPS
•> 50 Гб данных
•200 серверов        НЕ ОК !
V.2
Portal Users             Client Users




  Django                 API Server




               Storage
V.2
Portal Users             Client Users




  Django                 Scala + Lift




               Storage
SCALA

• Работает   на JVM

• Полностью   совместима с Java

• Статическая   типизация

• Лаконичность   и выразительность

• ООП   + ФП
V.2
Portal Users             Client Users




  Django                 Scala + Lift




               MongoDB
MONGODB

• Document   - Oriented        > db.users.findOne( {
                                      "phones.mob" : "+792194234"
                                  })


• Вторичные   индексы          {
                                   "_id" : ObjectId
                               ("4d94d822596f0e3f4d4a51bc"),
                               	    "name" : "Vasya",
• Язык   запросов              	
                               	
                                    "age" : 22,
                                    "phones" : {
                               	    	    "mob" : "+792194234",
                               	    	    "home" : "+812342341"
• Атомарные   апдейты          	    },
                               	    "roles" : [
                               	    	    "admin",
                               	    	    "staff"
• Скорость                     	    ]
                               }


• Автошардинг   и репликация
РЕЗУЛЬТАТЫ
                  TPS

500


375


250
                            450
125

      50          100
  0
      Old       Old tuned   New
ТЕСТЫ И CI
println("Trying to create group with slug $slug")
reqBody = [name: “Test Group”, slug: “test”, ... ]

builder.request(POST, JSON) {
  requestContentType = URLENC
  uri.path = "internal/groups/create.json"
  body = reqBody

    response.success = { resp, json ->
      println(json.toString())
      assertEquals(201, resp.status)
      assert json.name == reqBody.name
      assert json.description == reqBody.description
      assert json.slug == reqBody.slug.toLowerCase()
      assert json.creatorId == reqBody.creatorId
      assert json.counters.members == 1
      assert json.counters.notes == 0
    }

    response.failure = { resp, json ->
      println(resp.statusLine)
      println(json.toString())
      fail("Request for creating group $slug failed.")
    }
}
ТЕСТЫ И CI

• Scala   (main + unit) : 10 500

• Groovy    (functional): 5 500

• Прогон     при каждом Push

• Тестирование  интеграции
 с поиском, Twitter, S3, etc.
РАЗНОЕ

• Полнотекстовый      поиск: ElasticSearch

• Сборка: Gradle

• VCS: Git

• CI: Jenkins   (ex-Hudson)
ХОСТИНГ


• Май   2009 - OVH (Франция)

• Декабрь   2010 - Exchange Guru (NY)

• Апрель   2011 - Amazon EC2
US-EAST-1B
VPC
              HAProxy               HAProxy


      API                  API                Portal



      DB1                  DB2                DB3



  Memcached             ElasticSearch     Stats & Munin
21 АПРЕЛЯ 2011
US-EAST-1B                US-EAST-1B               US-EAST-2B
        HAProxy                   HAProxy


   API           Portal      API          Portal


        DB Master             DB Replica 1           DB Replica 2


  ...      ...      ...     ...     ...      ...
• Сервера   и реплики в нескольких зонах

• Бэкап-реплика   в другом регионе

• Автоматическоеуправление конфигурацией для
 быстрого развёртывания (Opscode Chef)

• Полное   устранение SPOF (Memcached)

• Мониторинг   и алерты
СИНЯКИ И ШИШКИ

• Bleeding   edge не такой уж bleeding

• Scala: разработчиков   мало, но они в тельняшках

• Gradle   + Scalac - время сборки

• MongoDB     - просто RTFM

• EC2   - непостоянные IP-адреса
LOOKING FORWARD
• Уход   от tomcat и сервлетов

• Автоматизация   нагрузочного тестирования

• Comet   / Websockets

• Push   для мобильных

• Автоматическое   управление конфигурацией и
 развёртыванием
Q&A


Юрий Буянов
yuri.buyanov@e-legion.com     http://www.e-legion.ru
@digal                               http://goozy.com

More Related Content

Юрий Буянов «Архитектура Goozy»

  • 1. GOOZY В поисках идеальной архитектуры 2011, e-Legion ltd. Юрий Буянов Goozyware inc. @digal
  • 2. • Пара слов о проекте • Первая версия и первые проблемы • Новые требования и новая архитектура •В самом низу • Приключения с хостингом • Синяки и шишки • Looking Forward
  • 4. СПЕЦИФИКА • Социальность: пользователь хочет быть постоянно в курсе •2 req/min от каждого пользователя (даже когда он ничего не делает). • Вездесущность: работает на всех сайтах • Запрос при открытии каждой страницы.
  • 5. V.1 Portal Users Client Users Django Memcached MySQL
  • 9. ПОДРОБНЕЕ О НАГРУЗКЕ Portal Users Client Users Django Memcached MySQL
  • 10. ПОДРОБНЕЕ О НАГРУЗКЕ Portal Users Client Users Django Memcached MySQL
  • 11. LOAD TEST • Пропускная способность: 50 TPS • Отклик: 2500 ms
  • 12. НЕМНОГО ЧИСЕЛ • 11 000 пользователей • 1000 онлайн (в пике) •2 сервера • 500 мб данных
  • 13. НЕМНОГО ЧИСЕЛ • 11 000 пользователей • 11 000 пользователей • 1000 онлайн (в пике) • 23 000 стикеров •2 сервера • 30 000 комментариев • 500 мб данных •2 200 000 таймлайн-записей
  • 15. НОВЫЕ ТРЕБОВАНИЯ •1 000 000 пользователей •> 100 000 онлайн •> 10 000 TPS •> 50 Гб данных •200 серверов
  • 16. НОВЫЕ ТРЕБОВАНИЯ •1 000 000 пользователей •> 100 000 онлайн •> 10 000 TPS •> 50 Гб данных •200 серверов НЕ ОК !
  • 17. V.2 Portal Users Client Users Django API Server Storage
  • 18. V.2 Portal Users Client Users Django Scala + Lift Storage
  • 19. SCALA • Работает на JVM • Полностью совместима с Java • Статическая типизация • Лаконичность и выразительность • ООП + ФП
  • 20. V.2 Portal Users Client Users Django Scala + Lift MongoDB
  • 21. MONGODB • Document - Oriented > db.users.findOne( { "phones.mob" : "+792194234" }) • Вторичные индексы { "_id" : ObjectId ("4d94d822596f0e3f4d4a51bc"), "name" : "Vasya", • Язык запросов "age" : 22, "phones" : { "mob" : "+792194234", "home" : "+812342341" • Атомарные апдейты }, "roles" : [ "admin", "staff" • Скорость ] } • Автошардинг и репликация
  • 22. РЕЗУЛЬТАТЫ TPS 500 375 250 450 125 50 100 0 Old Old tuned New
  • 23. ТЕСТЫ И CI println("Trying to create group with slug $slug") reqBody = [name: “Test Group”, slug: “test”, ... ] builder.request(POST, JSON) { requestContentType = URLENC uri.path = "internal/groups/create.json" body = reqBody response.success = { resp, json -> println(json.toString()) assertEquals(201, resp.status) assert json.name == reqBody.name assert json.description == reqBody.description assert json.slug == reqBody.slug.toLowerCase() assert json.creatorId == reqBody.creatorId assert json.counters.members == 1 assert json.counters.notes == 0 } response.failure = { resp, json -> println(resp.statusLine) println(json.toString()) fail("Request for creating group $slug failed.") } }
  • 24. ТЕСТЫ И CI • Scala (main + unit) : 10 500 • Groovy (functional): 5 500 • Прогон при каждом Push • Тестирование интеграции с поиском, Twitter, S3, etc.
  • 25. РАЗНОЕ • Полнотекстовый поиск: ElasticSearch • Сборка: Gradle • VCS: Git • CI: Jenkins (ex-Hudson)
  • 26. ХОСТИНГ • Май 2009 - OVH (Франция) • Декабрь 2010 - Exchange Guru (NY) • Апрель 2011 - Amazon EC2
  • 27. US-EAST-1B VPC HAProxy HAProxy API API Portal DB1 DB2 DB3 Memcached ElasticSearch Stats & Munin
  • 29. US-EAST-1B US-EAST-1B US-EAST-2B HAProxy HAProxy API Portal API Portal DB Master DB Replica 1 DB Replica 2 ... ... ... ... ... ...
  • 30. • Сервера и реплики в нескольких зонах • Бэкап-реплика в другом регионе • Автоматическоеуправление конфигурацией для быстрого развёртывания (Opscode Chef) • Полное устранение SPOF (Memcached) • Мониторинг и алерты
  • 31. СИНЯКИ И ШИШКИ • Bleeding edge не такой уж bleeding • Scala: разработчиков мало, но они в тельняшках • Gradle + Scalac - время сборки • MongoDB - просто RTFM • EC2 - непостоянные IP-адреса
  • 32. LOOKING FORWARD • Уход от tomcat и сервлетов • Автоматизация нагрузочного тестирования • Comet / Websockets • Push для мобильных • Автоматическое управление конфигурацией и развёртыванием
  • 33. Q&A Юрий Буянов yuri.buyanov@e-legion.com http://www.e-legion.ru @digal http://goozy.com