Як масштабуватись з 1 до 100 000 користувачів

Через таке пройшло багато стартапів: щодня реєструються натовпи нових користувачів, а команда розробників щосили намагається підтримати роботу сервісу.

Це приємна проблема, але в мережі мало чіткої інформації, як акуратно масштабувати веб-додаток з нуля до сотень тисяч користувачів. Зазвичай зустрічаються або пожежні рішення, або усунення вузьких місць (а то й інше). Тому люди використовують досить шаблонні прийоми щодо масштабування свого аматорського проекту на щось справді серйозне.

Спробуємо відфільтрувати інформацію та записати основну формулу. Ми збираємося крок за кроком масштабувати наш новий сайт для обміну фотографіями Graminsta з 1 до 100 000 користувачів.

Запишемо, які конкретні дії необхідно зробити зі збільшенням аудиторії до 10, 100, 1000, 10 000 та 100 000 осіб.

1 користувач: 1 машина

Майже кожен додаток, будь то веб-сайт або мобільний додаток, є три ключові компоненти:

  • API
  • база даних
  • клієнт (саме мобільний додаток або веб-сайт)

База даних зберігає незмінні дані. API обслуговує запити до цих даних та навколо них. Клієнт передає дані користувачеві.

Я дійшов висновку, що набагато простіше розмірковувати про масштабування програми, якщо з погляду архітектури повністю розділити сутності клієнта та API.

Коли ми вперше починаємо створювати програму, всі три компоненти можна запускати на одному сервері. У певному сенсі це нагадує наше середовище розробки: один інженер запускає базу даних, API та клієнт на одному комп'ютері.

Теоретично, ми могли б розгорнути його на одному примірнику DigitalOcean Droplet або AWS EC2, як показано нижче:
Як масштабуватись з 1 до 100 000 користувачів
З урахуванням сказаного, якщо на сайті буде більше одного користувача, майже завжди має сенс виділити рівень бази даних.

10 користувачів: винесення БД в окремий рівень

Розділ бази даних на керовані служби, такі як Amazon RDS або Digital Ocean Managed Database, добре послужить нам протягом тривалого часу. Це трохи дорожче, ніж самостійний хостинг на одній машині або екземплярі EC2, але з цими службами ви з коробки отримуєте безліч корисних розширень, які стануть у нагоді в майбутньому: резервування по кількох регіонах, репліки читання, автоматичне резервне копіювання та багато іншого.

Ось як тепер виглядає система:
Як масштабуватись з 1 до 100 000 користувачів

100 користувачів: винесення клієнта в окремий рівень

На щастя, наш додаток дуже сподобався першим користувачам. Трафік стає більш стабільним, тому настав час винести клієнта в окремий рівень. Варто зазначити, що поділ сутностей є ключовим аспектом побудови масштабованого додатка. Оскільки одна частина системи отримує більше трафіку, ми можемо розділити її так, щоб керувати масштабування сервісу на основі специфічних шаблонів трафіку.

Ось чому мені подобається представляти клієнта окремо від API. Це дозволяє дуже легко розмірковувати про розробку під кількох платформ: веб, мобільний веб, iOS, Android, десктопні додатки, сторонні сервіси і т.д. Всі вони просто клієнти, які використовують один і той же API.

Наприклад, зараз наші користувачі найчастіше просять випустити мобільний додаток. Якщо розділити сутності клієнта та API, це стає простіше.

Ось як виглядає така система:

Як масштабуватись з 1 до 100 000 користувачів

1000 користувачів: додати балансувальник навантаження

Справи йдуть на лад. Користувачі Graminsta завантажують все більше фотографій. Кількість реєстрацій також зростає. Наш самотній API-сервер важко справляється з усім трафіком. Потрібно більше заліза!

Балансувальник навантаження – дуже потужна концепція. Ключова ідея в тому, що ми ставимо балансувальник перед API, а він розподіляє трафік окремими примірниками служби. Так здійснюється горизонтальне масштабування, тобто ми додаємо більше серверів з тим самим кодом, збільшуючи кількість запитів, які можемо обробляти.

Ми збираємося розмістити окремі балансувальники навантаження перед веб-клієнтом та перед API. Це означає, що можна запустити кілька інстансів, які виконують код API та код веб-клієнта. Балансувальник навантаження надсилатиме запити до того сервера, який менше навантажений.

Тут ми отримуємо ще одну важливу перевагу – надмірність. Коли один екземпляр виходить з ладу (можливо, перевантажується чи падає), то у нас залишаються інші, які, як і раніше, відповідають на запити, що входять. Якби працював єдиний екземпляр, то у разі збою впала б вся система.

Балансувальник навантаження також забезпечує автоматичне масштабування. Ми можемо його налаштувати, щоб збільшити кількість інстансів перед піковим навантаженням і зменшити, коли всі користувачі сплять.

З балансувальником навантаження рівень API можна масштабувати практично до нескінченності, просто додаємо нові екземпляри зі збільшенням кількості запитів.

Як масштабуватись з 1 до 100 000 користувачів

Примітка. Зараз наша система дуже схожа на те, що з коробки пропонують компанії PaaS, такі як Heroku або сервіс Elastic Beanstalk в AWS (тому вони такі популярні). Heroku поміщає БД на окремий хост, керує балансувальником навантаження з автоматичним масштабуванням та дозволяє розмістити веб-клієнт окремо від API. Це чудова причина, щоб використовувати Heroku для проектів або стартапів на ранній стадії — усі базові сервіси ви отримуєте із коробки.

10 000 користувачів: CDN

Можливо, слід зробити це з самого початку. Обробка запитів та прийом нових фотографій починають надто навантажувати наші сервери.

На даному етапі потрібно використовувати хмарний сервіс зберігання статичного контенту - зображень, відео та багато іншого (AWS S3 або Digital Ocean Spaces). Загалом наш API повинен уникати обробки таких речей, як видача зображень і закачування зображень на сервер.

Ще одна перевага хмарного хостингу - це CDN (в AWS цей додаток називається Cloudfront, але багато хмарних сховищ пропонують його з коробки). CDN автоматично кешує наші зображення у різних дата-центрах по всьому світу.

Хоча наш основний дата-центр може бути розміщений в Огайо, але якщо хтось запросить зображення з Японії, хмарний провайдер зробить копію і збереже її у своєму японському дата-центрі. Наступний, хто запитатиме це зображення в Японії, отримає його набагато швидше. Це важливо, коли ми працюємо з файлами великих розмірів, як фотографії або відео, які довго завантажувати та передавати через всю планету.

Як масштабуватись з 1 до 100 000 користувачів

100 000 користувачів: масштабування рівня даних

CDN дуже допоміг: трафік росте на повний хід. Знаменитий відеоблогер Мевід Мобрик щойно зареєструвався у нас і запостив свою «сторі», як вони кажуть. Завдяки балансувальнику навантаження рівень використання CPU та пам'яті на серверах API тримається на низькому рівні (запущено десять інстансів API), але ми починаємо отримувати багато таймаутів на запити… звідки взялися ці затримки?

Трохи покопавшись у метриках, бачимо, що CPU на сервері бази даних завантажений на 80-90%. Ми межі.

Масштабування шару даних, ймовірно, найскладніша частина рівняння. Сервери API обслуговують запити без збереження стану (stateless), тому ми просто додаємо більше інстансів API. Але з більшістю баз даних так зробити не вийде. Ми обговоримо про популярні реляційні системи управління базами даних (PostgreSQL, MySQL та ін.).

Кешування

Один із найпростіших способів збільшити продуктивність нашої бази даних – запровадити новий компонент: рівень кешу. Найбільш поширений спосіб кешування - сховище записів "ключ-значення" в оперативній пам'яті, наприклад, Redis або Memcached. У більшості хмар є керована версія таких сервісів: Elasticache на AWS та Memorystore на Google Cloud.

Кеш корисний, коли служба робить багато повторних викликів до БД для отримання однієї й тієї інформації. По суті, ми звертаємося до бази лише один раз, зберігаємо інформацію в кеші і більше її не чіпаємо.

Наприклад, у нашому сервісі Graminsta щоразу, коли хтось переходить на сторінку профілю зірки Мобрика, сервер API запитує в БД інформацію з його профілю. Це відбувається знову і знову. Оскільки інформація про профіль Мобрика не змінюється при кожному запиті, то відмінно підходить для кешування.

Кешуватимемо результати з БД в Redis за ключом user:id із терміном дії 30 секунд. Тепер, коли хтось заходить у профіль Мобрика, ми спочатку перевіряємо Redis і якщо дані там є, просто передаємо їх прямо з Redis. Тепер запити до найпопулярнішого профілю на сайті практично не навантажують базу даних.

Інша перевага більшості сервісів кешування в тому, що їх простіше масштабувати, ніж сервери БД. Redis має вбудований режим кластера Redis Cluster. Подібно до балансувальника навантаження1, він дозволяє розподіляти кеш Redis за кількома машинами (по тисячам серверів, якщо потрібно).

Багато великомасштабні програми використовують кешування, це абсолютно невід'ємна частина швидкого API. Прискорення обробки запитів і продуктивніший код — все це важливо, але без кешу практично неможливо масштабувати сервіс до мільйонів користувачів.

Репліки читання

Коли кількість запитів до БД зросла, ми можемо зробити ще одну річ — додати репліки читання в системі управління базами даних. За допомогою описаних вище керованих служб це можна зробити в один клік. Репліка читання залишатиметься актуальною в основній БД та доступна для операторів SELECT.

Ось наша система зараз:

Як масштабуватись з 1 до 100 000 користувачів

Подальші дії

Оскільки програма продовжує масштабуватись, ми продовжимо розділяти служби, щоб масштабувати їх незалежно один від одного. Наприклад, якщо ми починаємо використовувати Websockets, то є сенс витягти код обробки Websockets в окрему службу. Ми можемо розмістити її на нових інстансах за власним балансувальником навантаження, який може масштабуватись вгору та вниз залежно від відкритих з'єднань Websockets та незалежно від кількості HTTP-запитів.

Також продовжимо боротися з обмеженнями на рівні БД. Саме на даному етапі настав час вивчити партиціонування та шардування бази даних. Обидва підходи вимагають додаткових накладних витрат, проте дозволяють масштабувати БД практично до нескінченності.

Ми також хочемо встановити сервіс моніторингу та аналітики на зразок New Relic або Datadog. Це дозволить виявити повільні запити та зрозуміти, де потрібне покращення. У міру масштабування ми хочемо зосередитись на пошуку вузьких місць та їх усуненні – часто використовуючи деякі ідеї з попередніх розділів.

Джерела

Цей пост надихнутий одним із моїх улюблених постів про високу масштабованість. Я хотів трохи конкретизувати статтю для початкових стадій проектів та відв'язати її від одного вендора. Обов'язково прочитайте, якщо ви цікавитеся цією темою.

виноски

  1. Незважаючи на схожість з погляду розподілу навантаження між кількома інстансами, базова реалізація кластера Redis дуже відрізняється від балансувальника навантаження. [повернутись]

Як масштабуватись з 1 до 100 000 користувачів

Джерело: habr.com

Додати коментар або відгук