Як боротися з високим навантаженням на сервер

  1. ПЕРЕДЧАСНА ОПТИМІЗАЦІЯ РОБОТИ З БАЗОЮ ДАНИХ
  2. ПЕРЕДЧАСНА ОПТИМІЗАЦІЯ ЗА ВСЕ ДОДАТКИ В ЦІЛОМУ
  3. ПРО хіпстера І СРІБНУ КУЛЮ
  4. не перегинати

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

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

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

Як казав дідусь Кнут, передчасна оптимізація - корінь всіх зол. І в даній статті ми хочемо пройтися по її трьома видами, які бачимо найчастіше в вебразработке. це:

• передчасна оптимізація роботи з базою даних;

• передчасна оптимізація всього програми в цілому;

• надмірне захоплення хіпстерскімі технологіями в надії знайти срібну кулю.

ПЕРЕДЧАСНА ОПТИМІЗАЦІЯ РОБОТИ З БАЗОЮ ДАНИХ

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

В одній дружній нам компанії, якій, на жаль, тепер уже немає, розробники виходили з того, що гігантська кількість даних буде вже на старті. І розробку проекту почали з планування архітектури, яка дала б можливість легко і практично балансувати дані між будь-якою кількістю серверів. При цьому схема враховувала можливість додавання нової Шардена бази даних на льоту.

Розробники поверталися до цієї підсистемі кілька разів протягом двох років - вона не була повністю готова, а розробники, пов'язані з продуктової частиною, регулярно змінювали схеми БД. В результаті проект був закритий, а сили, які могли б бути кинуті на вдосконалення продуктової частини, були витрачені на створення підсистеми, яку ніколи не довелося використовувати.

На ділі - шардінг необхідний як рішення двох проблем:

1. Операції з БД в умовах величезного обсягу даних.

2. Масштабування навантаження на дискову запис.

Окремо хотілося б відзначити: в 99 з 100 випадків (і в умовах широкої доступності SSD в наші дні) завдання масштабування записи виникають далеко не відразу. Щоб контент створювався, користувача треба зацікавити. При цьому великі обсяги даних у вашій системі також не опиняться раптово і відразу - майже напевно у вас буде час на модифікацію архітектури в процесі роботи системи так, щоб вона могла масштабироваться по запису.

Що може цьому перешкодити і що дійсно варто зробити на початку? Ми скажемо крамольну річ: слід бути вкрай обережним з використанням будь-яких абстракцій доступу до бази даних. Так, ORM - це кльово і зручно, але, коли мова зайде про те, що запит треба розкидати по двом різним місцях, - тобі доведеться докопатися до самих глибин використовуваного ORM, щоб зрозуміти, як це реалізувати. Ми часто бачимо, як, здавалося б, просте завдання модифікації в умовах генерування SQL-запитів перетворюється на справжнє пекло.

Друга оптимізація з точки зору програміста, яку можна зробити, - це відразу передбачити, що серверів може бути декілька, і в момент вибору даних допустити те, що SQL-запит може бути виконаний на одному з декількох серверів. Тобто: у тебе є об'єкт доступу до БД, і у тебе є SQL-запит, який ти хочеш виконати. Похорошему, в тому місці, де ти виконуєш цей запит до сервера, ти повинен мати можливість безпосередньо вибрати сервер, до якого звертаєшся.

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

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

На одному з проектів - сайті з питаннями і відповідями, написаному на джанго, - ми бачили, як список питань протягом якогось кількості коду перед його отриманням був обмежений рядом критеріїв. З точки зору програміста все виглядало більш-менш ОК - час від часу до об'єкту списку просто доповнювався новий критерій. У підсумку ж ORM Джангі генерував запит на 25 group by, які експоненціально створювали навантаження на базу в міру зростання обсягу оброблюваних даних. І якби запит був у вигляді простого SQL - ще залишався шанс подумати, як оптимізувати процедуру, але в цьому випадку все було сильно ускладнено.

І якби запит був у вигляді простого SQL - ще залишався шанс подумати, як оптимізувати процедуру, але в цьому випадку все було сильно ускладнено

Наостанок про частину з оптимізацією БД. Як ми вже сказали, ми частіше бачимо навантаження на читання, ніж на запис. Організувати велике навантаження на запис - це окремий успіх :). А навантаження на читання можна балансувати взагалі без особливих змін з боку коду. Якщо ми готові до того, що під час виконання запиту ми можемо вибрати сервер, то, якщо нам треба балансувати читання, ми можемо просто створити n-ну кількість slave-серверів. А при виконанні селекта рандомно вибирати один з серверів, на якому вже і виконувати цей селект. А запис робити тільки в один окремий master.

ПЕРЕДЧАСНА ОПТИМІЗАЦІЯ ЗА ВСЕ ДОДАТКИ В ЦІЛОМУ

Ця історія починається так само: одні наші друзі чекали сто мільйонів користувачів. Послухали доповідь про те, як все влаштовано в Яндексі, і захотіли зробити у себе так само. Вирішили, що nginx буде збирати веб-сторінки по шаблонах в XSLT / XML, що описує загальну структуру компонентів на сторінці. При запиті nginx парсит файл, бачить, які використовуються компоненти, і по кожному компоненту звертається на бекенд

за його відрендерене версією, передаючи ідентифікатор сесії, щоб зберегти стан. А відповідно, бекенд всієї платформи розуміє, як отримувати такі запити і генерувати висновок компонента.

В результаті створення цього рішення зайняло більше року, залучені C-розробники запросили передоплату, але так і не зробили модуль, який би реалізовував даний функціонал в nginx. Втім, він і не потрібен був, так як після двох років розробки проект довелося згорнути.

Втім, він і не потрібен був, так як після двох років розробки проект довелося згорнути

У наш XXI століття хмарних технологій, де CPU-ресурси масштабируются досить дешево по вертикалі, а балансувальник навантаження включаються за дуже короткий час, створювати заздалегідь якийсь специфічний код для балансування додатки, на наш погляд, здається зайвою роботою. Що ви дійсно можете зробити, так це передбачити, щоб сесії користувачів не були прив'язані до конкретної вебмашіне, і після цього просто клонувати то кількість вебінстансов, яке вам потрібно в очікуванні оптимізації коду.

Інша крайність, яку ми зустрічали в своїй практиці, - це ускладнення роботи зі статичним вмістом, завантаженим користувачами. У розрахунку на високе навантаження розробники створюють підтримку кластера nginx-серверів з WebDAV-модулем. Кожен файл, що завантажується користувачем, спочатку лягав на проміжний сервер, а слідом вирушав на WebDAV-сервер, звідки пізніше віддавався nginx'ом. Інформація про місце зберігання цього файлу зберігалася в базі. Реальна навантаження на цей проект так і не прийшла.

Дійсно серйозною проблемою, на наш погляд, для більшості проектів є лише повна відсутність будь-якого принципу зберігання файлів - коли все складається в одну директорію. І коли в один прекрасний день ти розумієш, що файлів стало під 70 тисяч і ext4 не дає тобі записувати нові, ти або вигадуєш розумну схему розподілу файлів, або переїздиш, наприклад на XFS. У другому випадку тебе вже ніщо не врятує.

Як ми пропонуємо вирішувати це питання всім клієнтам:

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

2. Якщо розділення даних на свіжі і не дуже немає, то можна вираховувати два різних цифрових хешу від імені файлу, а потім використовувати їх в якійсь структурі директорій, всередині якої вже складати сам файл.

Але що робити, якщо ми боїмося, що сервер не вивезе навантаження на читання? На першому етапі нас врятує lsyncd, який допоможе розподілити статику за кількома окремими серверів і тим самим розподілити навантаження на її читання. А так як статика скрізь однакова, то читати її можна з будь-якого сервера. При необхідності можна буде легко додавати в схему додаткові потужності, поки програмісти нарешті не придумають більш тонку схему. Але будь обережний - пам'ятай, що немає нічого більш постійного, ніж якийсь тимчасовий милицю. Від них обов'язково потрібно буде позбутися.

ПРО хіпстера І СРІБНУ КУЛЮ

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

наприклад, ті ж NoSQL бази даних. В захопленні NoSQL як панацеєю від проблем з БД насправді є дуже багато підводних каменів. Наприклад, на більшості NoSQL рішень синхронізація даних на диск - це глобальний лок, під час якого робота з базою даних вкрай важким. При використанні редису, якщо знаходяться в ньому дані тобі потрібні, у тебе є два виходи:

1. Мати на окремій машині слейв, який буде періодично дампи дані.

2. Відключити дамп на майстра, не робити слейв, постійно молитися, що нічого не впаде.

По суті, дві головні проблеми всіх нових технологій слідують одна з одною:

1. Сирість рішення.

2. Відсутність бази знань по існуючих проблем.

Якщо у тебе є проблема з MySQL і Postgres, ти можеш написати про неї в гуглі і майже напевно знайдеш мільйон людей, які зустрічалися з подібною до тебе. Якщо ж проблема пов'язана з якоюсь свіжою технологією, великий ризик, що доведеться виходити на розробника і разом розбиратися, що до чого. Ми самі одного разу занадто захопилися подібними речами (і це відбулося навіть вже на відносно відомому і довго розробляється Openstack'е) - замість звичних методів віртуалізації хотілося мати можливість керувати віртуальними машинами «як в амазон». Для цього ми вибрали Openstack, з яким мучилися протягом наступного місяця. Основна причина страждань - вогкість і необхідність підтримки. Для того щоб запустити віртуальну машину в Openstack, працюють п'ять Python-демонів, взаємодія між якими йде через RabbitMQ, а код постійно змінюється. Ясна річ, що зламатися там може все що завгодно, і воно ламається.

не перегинати

З іншого боку, бути зовсім вже ретроградом теж небезпечно. Давай згадаємо Perl-розробників (ми зовсім не хочемо образити Perl-розробників), які говорили, що Perl краще, ніж PHP, Perl краще Python, Perl краще Ruby і так далі. І зараз ми бачимо величезну кількість Perl-розробників, ринок для яких поступово закривається. Як же бути?

Головне - знайди кого-небудь, хто пройшов тернистий шлях обраної технології до тебе :). У дуже багатьох людей є досить вільного часу, а стартапи, які виділяють по два роки на всякі технологічні рішення, завжди будуть існувати. Вибрав хитру технологію, про яку всі пишуть? Знайди хлопців, які вже пробували і допоможуть, наприклад нас :)

Що може цьому перешкодити і що дійсно варто зробити на початку?
Але що робити, якщо ми боїмося, що сервер не вивезе навантаження на читання?
Як же бути?
Вибрав хитру технологію, про яку всі пишуть?