Відкриття думок
Як ви прийшли до висновку, що деякі частини системи краще їздять іншою мовою? Ви відчуваєте проблеми з роботою? Наскільки серйозні ці проблеми? Якщо це може бути швидше, чи важливо, щоб воно було швидше?
Асинхронія з однонитковою стрічкою
Існує кілька питань та інших веб-ресурсів, які вже вирішують відмінності, плюси та мінуси однопотокової асинхронії та одночасності багатопотокових. Цікаво читати про те, як працює асинхронна модель Node.js з однопоточним зв’язком, коли введення-виведення є основним вузьким місцем, і одразу існує багато багатьох запитів.
Скручені, Торнадо та інші асинхронні моделі відмінно використовують однониткові. Оскільки у багатьох веб-програмуваннях є багато вводу-виводу (мережа, база даних тощо), час, витрачений на очікування віддалених дзвінків, значно збільшується. Це час, який можна витратити на інші речі - наприклад, відхилення інших дзвінків до бази даних, надання сторінок та генерування даних. Використання цієї однониткової надто великої кількості.
Однією з найбільших переваг однопотокової асинхронії є те, що вона використовує набагато менше пам'яті. У багатопотоковому виконанні кожен потік вимагає певної кількості зарезервованої пам'яті. Зі збільшенням кількості потоків збільшується і обсяг пам'яті, необхідний лише для існування потоків. Оскільки пам’ять обмежена, це означає, що існує кількість меж потоку, які можна створити будь-коли.
Приклад
Що стосується веб-сервера, зробіть вигляд, що кожному запиту надається власний потік. Скажімо, для кожного потоку потрібно 1 Мб пам'яті, а веб-сервер має 2 Гб оперативної пам’яті. Цей веб-сервер зможе обробити (приблизно) 2000 запитів в будь-який момент часу, перш ніж просто не вистачить пам'яті для обробки.
Якщо ваше навантаження значно вище, ніж це, запити знадобляться дуже довго (коли очікуєте завершення старих запитів), або вам доведеться закидати більше серверів у кластер, щоб розширити кількість можливих одночасних запитів .
Паралельність багатопотокових
Паралельність із декількома потоками покладається на виконання декількох завдань одночасно. Це означає, що якщо нитка заблокована, очікуючи на виклик бази даних, щоб повернутися, інші запити можуть бути оброблені одночасно. Використання ниток є нижчим, але кількість виконуваних потоків значно більша.
Багатопотоковий код також набагато складніше міркувати. Існують проблеми із блокуванням, синхронізацією та іншими проблемами веселої одночасності. Однопоточна асинхронія не страждає від однакових проблем.
Однак багатопотоковий код набагато ефективніший для процесорів, що інтенсивно працюють . Якщо немає можливості для потоку «поступатись» (наприклад, мережевий дзвінок, який зазвичай блокується), однопотокова модель просто не матиме жодної однорідності.
Обидва можуть співіснувати
Звичайно, між ними перекриваються; вони не є взаємовиключними. Наприклад, багатопотоковий код можна записати не блокуючим способом, щоб краще використовувати кожен потік.
Суть
Є багато інших питань, які слід розглянути, але мені подобається думати про такі два:
- Якщо ваша програма пов'язана з входом / виводом , то однонитка асинхронія, ймовірно, буде працювати досить добре.
- Якщо ваша програма пов'язана з процесором , то, мабуть, найкраща буде багатопотокова система.
У вашому конкретному випадку вам потрібно визначити, який вид асинхронної роботи виконується, і як часто ці завдання виникають.
- Чи трапляються вони на кожен запит? Якщо це так, пам'ять, ймовірно, стане проблемою у міру збільшення кількості запитів.
- Чи замовлені ці завдання? Якщо це так, вам доведеться розглянути можливість синхронізації, якщо використовувати декілька потоків.
- Ці завдання CPU є інтенсивними? Якщо так, чи здатна однонитка не відставати від навантаження?
Немає простої відповіді. Ви повинні врахувати, якими є випадки використання, та спроектувати їх відповідно. Іноді краще асинхронна однопоточна модель. В інших випадках потрібно використовувати ряд ниток для досягнення масивної паралельної обробки.
Інші міркування
Є й інші питання, які потрібно також врахувати, а не просто модель одночасності, яку ви обрали. Ви знаєте Ерланга чи Клуджура? Як ви думаєте, ви могли б написати безпечний багатопотоковий код однією з цих мов, щоб покращити продуктивність вашої програми? Чи знадобиться багато часу, щоб швидко набратися однією з цих мов, і чи допоможе вам мова в майбутньому?
Як щодо труднощів, пов’язаних із спілкуванням між цими двома системами? Чи буде надмірно складним підтримувати дві окремі системи паралельно? Як система Erlang отримає завдання від Django? Як Ерланг передасть ці результати назад до Джанго? Чи досить продуктивність є проблемою, що варте додаткової складності?
Фінальні думки
Я завжди вважав, що Джанго є досить швидким, і його використовують деякі сайти, де дуже торгують людьми. Ви можете зробити кілька оптимізацій продуктивності, щоб збільшити кількість паралельних запитів та часу відповіді. Щоправда, я досі нічого не робив із селерою, тому звичайні оптимізації продуктивності, ймовірно, не вирішать жодних проблем, які можуть виникнути з цими асинхронними завданнями.
Звичайно, завжди є можливість кинути більше обладнання на вирішення проблеми. Чи дешевше забезпечення нового сервера дешевше, ніж вартість розробки та обслуговування абсолютно нової підсистеми?
На сьогодні я задав занадто багато питань, але це був мій намір. Відповідь не буде простою без аналізу та додаткових деталей. Вміння проаналізувати проблеми зводиться до того, щоб знати питання, які потрібно задати, але, сподіваюся, я допоміг на цьому фронті.
Моє відчуття кишки говорить про те, що переписувати іншою мовою не потрібно. Складність та вартість, ймовірно, будуть занадто великими.
Редагувати
Відповідь на подальші дії
У подальшому поданні представлено кілька дуже цікавих випадків використання.
1. Django, що працює поза HTTP-запитами
Ваш перший приклад включав читання тегів NFC, а потім запит до бази даних. Я не думаю, що написання цієї частини іншою мовою буде для вас корисним, просто тому, що запит до бази даних або сервера LDAP буде пов'язаний мережевим входом / виводом (і, можливо, продуктивністю бази даних). З іншого боку, кількість одночасних запитів буде пов'язана самим сервером, оскільки кожна команда управління буде виконуватися як власний процес. Настане час налаштування та час виходу, який впливає на продуктивність, оскільки ви не надсилаєте повідомлення вже запущеному процесу. Однак ви зможете надсилати кілька запитів одночасно, оскільки кожен процес буде ізольованим.
У цьому випадку я бачу два шляхи, які ви можете дослідити:
- Переконайтеся, що ваша база даних здатна обробляти декілька запитів одночасно з об'єднанням з'єднань. (Наприклад, Oracle вимагає відповідно налаштувати Django
'OPTIONS': {'threaded':True}
.) На рівні бази даних або на рівні Django можуть бути подібні параметри конфігурації, які можна налаштувати для власної бази даних. Незалежно від того, якою мовою ви пишете запити до бази даних, вам доведеться чекати, коли ці дані повернуться, перш ніж ви зможете засвітити світлодіоди. Виконання коду запиту може змінити значення, і Django ORM не блискавично ( але , як правило, досить швидко).
- Мінімізуйте час налаштування / відстеження. Постійно виконуйте процес і надсилайте до нього повідомлення. (Виправте мене, якщо я помиляюся, але саме на цьому фокусується ваше первісне запитання.) Чи цей процес написано на Python / Django чи іншою мовою / рамкою, висвітлено вище. Мені не подобається так часто використовувати команди управління. Чи можливо постійно працювати невеликий шматок коду, який штовхає повідомлення читачів NFC на чергу повідомлень, яку потім Селері читає і передає Джанго? Налаштування та припинення невеликої програми, навіть якщо вона написана на Python (але не Django!), Має бути кращою, ніж запуск та зупинення програми Django (з усіма її підсистемами).
Я не впевнений, який веб-сервер ви використовуєте для Django. mod_wsgi
для Apache дозволяє налаштувати кількість процесів і потоків у межах процесів, які запитує служба. Не забудьте налаштувати відповідну конфігурацію вашого веб-сервера, щоб оптимізувати кількість справних запитів.
2. "Повідомлення" із сигналами Джанго
Ваш другий випадок використання також досить цікавий; Я не впевнений, чи маю на це відповіді. Якщо ви видаляєте екземпляри моделей і хочете оперувати ними пізніше, можливо, можливо їх серіалізувати, JSON.dumps
а потім десеріалізувати JSON.loads
. Пізніше повністю відтворити графік об'єкта буде неможливо (запит пов'язаних моделей), оскільки пов'язані поля ледаче завантажуються з бази даних, і це посилання більше не буде існувати.
Іншим варіантом було б якось позначити об’єкт для видалення та видалити його лише в кінці циклу запиту / відповіді (після того, як усі сигнали будуть обслужені). Для здійснення цього може знадобитися спеціальний сигнал, а не покладатися на нього post_delete
.