Brubeck — швидкий, statsd-сумісний агрегатор метрик від GitHub



Історія появи

Однією з головних цілей команди розробників GitHub завжди була висока продуктивність. У них навіть існує приказка: «it's not fully shipped until it's fast» (продукт вважається готовим тільки тоді, коли він працює швидко). А як зрозуміти, що щось працює швидко чи повільно? Потрібно міряти. Вимірювати правильно, надійно вимірювати, виміряти завжди. Потрібно стежити за вимірами, візуалізувати різні метрики, тримати руку на пульсі, особливо, коли маєш справу з високонавантаженими онлайн системами, такими як GitHub. Тому метрики — це інструмент, що дозволяє команді надавати настільки швидкі і доступні сервіси, майже без даунтаймов.

У свій час GitHub одними з перших запровадили у себе інструмент під назвою statsd від розробників з Etsy. statsd — це агрегатор метрик, написаний на Node.js. Його суть полягала в тому, щоб збирати всілякі метрики й агрегувати їх на сервері, для подальшого збереження в будь-якому форматі, наприклад, Graphite у вигляді даних на графіку. statsd — це хороший інструмент, побудований на UDP сокетах, зручний у використанні як на основному Rails додатку, так і для збору найпростіших метрик, на зразок виклику nc-u. Проблема з ним почала виявлятися пізніше, у міру зростання кількості серверів та метрик, які надсилаються в statsd.

Так, наприклад, деякі метрики показувалися некоректно, а деякі, особливо нові, взагалі не збиралися. Виною тому були майже 40%-ті втрати UDP пакетів, які просто не встигали обробитися і відкидалися. Природа однопотокового Node.js з використанням єдиного UDP сокета дала про себе знати.
Але масштабувати було не так просто. Для того, щоб розподілити збір і обробку пакетів з декількох серверів, потрібно було шардировать не по IP, а за самим метрик, інакше б на кожному сервері був свій набір даних для всіх показників. А завдання шардирования за метрик непроста, для її вирішення GitHub написав свій парсер UDP пакетів та балансування за назвою метрики.
Це згладило ситуацію, дозволило збільшити кількість инстансов statsd до чотирьох, але було півзаходом:


4 сервера statsd, ледве збирають метрики, плюс самописний балансувальник навантаження, що займається парсингом UDP пакетів, в результаті змусив переписати все більш правильно, на чистому, з нуля, зберігши зворотну сумісність. Так появися Brubeck.

Brubeck

Але переписування Node.js додатки (event-loop, написаний на основі libuv) на чистий, з використанням того ж самого libuv — сумнівне заняття. Тому вирішено було переглянути саму архітектуру програми.

По-перше, відмовилися від event-loop на сокеті. Дійсно, коли в тебе ллється 4 мільйона пакетів в секунду, немає сенсу кожен раз крутитися в циклі і питати, чи не з'явилися нові дані для читання, так як, швидше за все, вони там вже з'явилися, і не одні :)
Event-loop замінили на пул потоків воркеров, що використовують один загальний сокет з серіалізацією доступу до нього. Пізніше, механізм поліпшили ще, додавши підтримку SO_REUSEPORT для сокетів з linux 3.9, що дозволило відмовитися від серіалізації доступу воркеров до сокета в самому агрегаторі. (прим. по цій темі цікаво буде почитати статтю як nginx впровадив підтримку SO_REUSEPORT).

По-друге, наявність декількох потоків, що працюють з одними і тими ж метриками, означає, що у нас поділ даних. Для безпечного доступу до подільних даними необхідний механізм синхронізації доступу, наприклад, локі (lock), що не є добре в умовах високої конкуренції за доступ до даних і при необхідності високої продуктивності. На допомогу приходять lock-free алгоритми, зокрема, lock-free реалізація хеш-таблиці, в якій зберігаються метрики. (насправді там lock-free тільки на читання, а на запис optimistic locking, але це не страшно для додатків з високим reads-to-writes rate, т. к. метрики додаються і видаляються набагато рідше, ніж приходять в них самі дані).

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

Результат

Проста багатопотокова архітектура агрегатора дозволила добитися непоганих результатів: протягом останніх двох років єдиний сервер з Brubeck доріс до обробки 4.3 мільйона метрик в секунду, без втрати пакетів навіть у піковому навантаженні. Вся інфа і дані достовірно взяті з блогу розробників.

Brubeck був викладений в open-source: github.com/github/brubeck
У ньому вже є багато з statsd, але ще не все. На даний момент розробка ведеться активно, співтовариство знаходить баги і швидко виправляє.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.