Це стаття зі світу Python, але вона все ще застосовна до всієї сфери програмування, хоча багатопотокність дозволяє швидше обробляти запити, але існує й межа, зелені (мікропотоки) потоки — це рішення.
Багатопотокова розробка програмного забезпечення вирішує велику кількість проблем, особливо для мережевих додатків, які потребують вимогливої продуктивності для швидкої реакції користувачів. На жаль, багатопотокність недостатньо для розв'язання масштабуПаралельністьСексуальні проблеми.
Вирішення цих проблем вимагає зміни моделей програмування з використанням асинхронних подій та механізмів зворотного виклику. У Druva ми створили бібліотеку на основі Python під назвою Dhaga для розв'язання масштабних проблемПаралельність, тоді як модель програмування не потребує суттєвих змін.
Розробники програмного забезпечення живуть у одному з нихПаралельністьсвіт. Потоки сьогодні є першокласними громадянами, особливо під час розробки, особливо коли ваш додаток виконує інтенсивні мережеві операції, як-от система inSync (продукт для синхронізації мережевої безпеки), як Druva. Багатопотокність робить потік програмного коду для мережевих операцій простим і впорядкованим. Коли нашому додатку потрібні покращення продуктивності, його можна покращитиЕластичність, ми можемо збільшити кількість потоків.
Але коли йдеться про тисячі масштабівПаралельністьЗапитів, потоків — це недостатньо.
Ми виявили, що багатопотокова робота має такі недоліки: 1. Клієнт системи inSync повинен резервувати велику кількість файлів на сервер через мережеві RPC-виклики. Типовий спосіб для розробників прискорити процес — це використання потоків. Однак продуктивність, яку забезпечує багатопотоковість, підвищує вартість пам'яті та процесора; Розробникам потрібно підтримувати баланс між швидкістю та кількістю потоків.
2. Наші сервери мають працювати між системою inSync і тисячами клієнтівПаралельністьЗ'єднання та сповіщення. Для ефективної обробки з'єднань ми використовуємо потоки для обробки запитів. Але зростаюча кількість клієнтів систем inSync також означає, що нам доводиться продовжувати збільшувати кількість потоків, що споживає багато серверної пам'яті та процесора.
3. Наш веб-сервер має обробляти тисячі паралельних HTTP-запитів. Більшість роботи робиться на мережевих сокетах, які приймають і передають дані та передають їх на бекенд системи inSync. Це змушує більшість потоків чекати на мережеві операції. Причиною проблеми C10K є те, що при тисячі синхронних запитів до веб-сервера генерація потоку для кожного запиту є досить немасштабованою (масштабуванням).
Обмеження асинхронних фреймворків Багато асинхронних фреймворків, включно з Twisted, Tornado Tornado та asyncore, можуть допомогти розробникам відійти від популярних способів використання потоків. Ці фреймворки базуються на неблокуючих сокет і механізмах зворотного виклику (подібно до Node.js). Якщо ми будемо використовувати ці фреймворки як є, основні частини нашого коду Druva доведеться рефакторити. Це не те, чого ми хочемо. Рефакторинг коду збільшує цикли розробки та тестування, заважаючи нам відповідати вимогам масштабу. Враховуючи, що кілька частин продукту мають бути масивними, кожному з нас доведеться їх рефакторити — тому й зусилля подвоїти або потроїти.
Щоб уникнути надмірних змін у коді, нам довелося відмовитися від прямого використання існуючого фреймворку. На щастя, ми знайшли корисні інструменти.
Оскільки ми хочемо контролювати виконання коду на мережевому введенні/виводі, нам потрібен спосіб розділити потік на мікропотоки. Ми знаходимоЗелені квіти。 Вона забезпечує неявне планування мікропотоків, яке називається ко-рутинею корутиною. Іншими словами. Це корисно, коли хочеш контролювати роботу коду. Можна створювати мікропотоки для власних розкладів, бо контролювати, коли грінлети дають паузи. Це ідеально для нас, бо дає повний контроль над розкладом нашого коду.
Tornado — це простий, не блокуючий веб-серверний фреймворк, написаний на Python, призначений для обробки тисяч асинхронних запитів. Ми використовуємо його основний компонент — IOLoop IOStream. IOLoop — це цикл подій вводу/виводу з неблокуючим сокетом; Він використовує epoll (на Linux) або черги (BSD і Mac OS X), інакше обирайте (на Windows), якщо вони доступні. IOStream надає неблокуючі роз'єми, такі як зручне пакування для читання та запису. Ми делегуємо всі операції сокета Tornado, а потім використовуємо зворотні виклики для запуска операцій з кодом (примітка banq: дуже схоже на Node.js механізм).
Це хороший початок, але нам потрібно більше. Якщо ми використаємо наведений модуль безпосередньо в нашому коді, багато нашого RPC-коду доведеться змінити: планування RPC через грінлети, переконатися, що грінлети не блокуються (якщо грінлети забиваються, це засмічить весь потік і всі інші), обробляти функції зворотного виклику з tornado.
Нам потрібна абстракція для управління та організації зелених листів, щоб уникнути їх перевантаження зовнішніми викликами, і ця абстракція може бути значно масштабованою за межі потоків. Ця абстракція є Dhaga, що дозволяє програмувати потік коду додатку як традиційну синхронну послідовність, але виконання є асинхронним.
Дхага (від хінді, що означає нитка) — це каркас виконання легкої нитки, яку ми абстрагуємо. Клас Dhaga походить від greenlets і використовує стек-комутацію для виконання кількох потоків коду в одному потоці операційної системи. Потоки однієї операційної системи виконують кілька дхагасів за допомогою спільного планування. Щоразу, коли dhaga чекає (переважно чекає на повернення RPC-виклику), вона передає керування батьківському рівню (тобто контексту виконання потоку на рівні ОС, який його створив). Рівень батьків потім призначає ще одну дхагу, щоб бути готовою до запуску. Виклик RPC буде переданий на веб-сервер торнадо для асинхронного запису сокета, а потім реєструється зворотний виклик при поверненні, і коли цей RPC повернеться, очікувана дхага додається до виконуваної черги і захоплюється батьківським потоком. (Примітка Банку: схоже на node.js принцип)
Ми можемо використовувати Dhaga замість потоків для операцій з високою затримкою, а також використовуємо 512 dhagas в одному потоці, коли кількість потоків перевищує розумний ліміт пропускної здатності.
|