Мысли открытия
Как вы пришли к выводу, что некоторые части системы будут лучше на другом языке? Вы испытываете проблемы с производительностью? Насколько серьезны эти проблемы? Если это может быть быстрее, важно ли это быстрее?
Однопоточная асинхронность
Есть несколько вопросов и других веб-ресурсов, которые уже имеют дело с различиями, плюсами и минусами однопоточной асинхронности и многопотокового параллелизма. Интересно прочитать о том, как однопоточная асинхронная модель Node.js работает, когда ввод-вывод является основным узким местом, и одновременно обрабатывается много запросов.
В Twisted, Tornado и других асинхронных моделях отлично используется однопоточная обработка. Поскольку во многих веб-программах много операций ввода-вывода (сеть, база данных и т. Д.), Время ожидания удаленных вызовов значительно увеличивается. Это время, которое можно потратить на другие вещи, такие как запуск других вызовов базы данных, рендеринг страниц и генерация данных. Использование этого единственного потока чрезвычайно высоко.
Одним из главных преимуществ однопоточной асинхронности является то, что она использует гораздо меньше памяти. В многопоточном исполнении каждому потоку требуется определенный объем зарезервированной памяти. По мере увеличения количества потоков увеличивается объем памяти, необходимый только для существования потоков. Поскольку память ограничена, это означает, что существуют ограничения на количество потоков, которые могут быть созданы в любой момент времени.
пример
В случае веб-сервера, притворяться, что каждый запрос имеет свой собственный поток. Допустим, для каждого потока требуется 1 МБ памяти, а на веб-сервере 2 ГБ ОЗУ. Этот веб-сервер будет способен обрабатывать (приблизительно) 2000 запросов в любой момент времени, прежде чем просто не хватит памяти для дальнейшей обработки.
Если ваша нагрузка значительно выше этой, запросы будут занимать очень много времени (при ожидании завершения более старых запросов), или вам придется добавить больше серверов в кластер, чтобы увеличить число одновременных запросов. ,
Многопоточный параллелизм
Многопоточный параллелизм вместо этого полагается на выполнение нескольких задач одновременно. Это означает, что если поток заблокирован в ожидании возврата из базы данных, одновременно могут быть обработаны другие запросы. Использование потоков ниже, но число выполняющихся потоков намного больше.
Многопоточный код также гораздо сложнее рассуждать. Есть проблемы с блокировкой, синхронизацией и другими забавными проблемами параллелизма. Однопоточная асинхронность не страдает от тех же проблем.
Однако многопоточный код гораздо эффективнее для задач, интенсивно использующих процессор . Если у потока нет никаких возможностей для «выдачи» - например, сетевого вызова, который обычно блокирует - однопотоковая модель просто не будет иметь никакого параллелизма вообще.
Оба могут сосуществовать
Конечно, между ними есть совпадение; они не являются взаимоисключающими. Например, многопоточный код может быть написан неблокирующим образом, чтобы лучше использовать каждый поток.
Суть
Есть много других вопросов для рассмотрения, но мне нравится думать о двух, как это:
- Если ваша программа связана с вводом / выводом , то однопоточная асинхронность, вероятно, будет работать достаточно хорошо.
- Если ваша программа связана с процессором , то лучше всего будет использовать многопоточную систему.
В вашем конкретном случае вам необходимо определить, какая асинхронная работа выполняется, и как часто эти задачи возникают.
- Они встречаются при каждом запросе? Если это так, память, вероятно, станет проблемой по мере увеличения количества запросов.
- Упорядочены ли эти задачи? Если это так, вам придется рассмотреть вопрос о синхронизации при использовании нескольких потоков.
- Являются ли эти задачи интенсивным использованием процессора? Если да, может ли один поток справиться с нагрузкой?
Там нет простого ответа. Вы должны рассмотреть, каковы ваши варианты использования, и спроектировать соответственно. Иногда лучше использовать асинхронную однопоточную модель. В других случаях требуется использование нескольких потоков для достижения массовой параллельной обработки.
Другие соображения
Есть и другие проблемы, которые вы должны рассмотреть, а не только модель параллелизма, которую вы выбираете. Вы знаете Erlang или Clojure? Как вы думаете, сможете ли вы написать безопасный многопоточный код на одном из этих языков, чтобы повысить производительность своего приложения? Потребуется ли много времени, чтобы освоить один из этих языков, и будет ли язык, который вы изучаете, принесет вам пользу в будущем?
Как насчет трудностей, связанных со связью между этими двумя системами? Будет ли слишком сложно поддерживать две отдельные системы параллельно? Как система Erlang будет получать задания от Django? Как Эрланг сообщит об этих результатах Джанго? Является ли производительность достаточно серьезной проблемой, что дополнительная сложность того стоит?
Последние мысли
Я всегда считал, что Django достаточно быстр, и он используется некоторыми сайтами с очень большой посещаемостью. Существует несколько способов оптимизации производительности, позволяющих увеличить количество одновременных запросов и время отклика. Следует признать, что до сих пор я ничего не делал с Celery, поэтому обычная оптимизация производительности, вероятно, не решит никаких проблем, которые могут возникнуть у вас с этими асинхронными задачами.
Конечно, всегда есть предложение использовать больше оборудования для решения этой проблемы. Является ли стоимость предоставления нового сервера дешевле стоимости разработки и обслуживания совершенно новой подсистемы?
Я задал слишком много вопросов на данный момент, но это было мое намерение. Ответ не будет легким без анализа и дальнейших подробностей. Возможность анализировать проблемы сводится к знанию задаваемых вопросов, хотя ... надеюсь, я помог в этом вопросе.
Мое инстинктивное чувство говорит, что переписывать на другом языке не нужно. Сложность и стоимость, вероятно, будут слишком велики.
редактировать
Ответ на продолжение
Ваше продолжение представляет несколько очень интересных случаев использования.
1. Django работает вне HTTP-запросов
Ваш первый пример включал чтение тегов NFC и запрос к базе данных. Я не думаю, что написание этой части на другом языке будет настолько полезным для вас, просто потому, что запрос к базе данных или серверу LDAP будет связан с сетевым вводом-выводом (и, возможно, производительностью базы данных). С другой стороны, количество одновременных запросов будет зависеть от самого сервера, поскольку каждая команда управления будет выполняться как собственный процесс. Будет время установки и демонтажа, которое влияет на производительность, так как вы не отправляете сообщения уже запущенному процессу. Однако вы сможете отправлять несколько запросов одновременно, поскольку каждый из них будет изолированным процессом.
В этом случае я вижу два пути, которые вы можете исследовать:
- Убедитесь, что ваша база данных способна обрабатывать несколько запросов одновременно с пулами соединений. (Например, Oracle требует соответствующей настройки Django
'OPTIONS': {'threaded':True}
.) На уровне базы данных или на уровне Django могут быть аналогичные параметры конфигурации, которые вы можете настроить для своей собственной базы данных. Независимо от того, на каком языке вы пишете запросы к базе данных, вам придется подождать, пока эти данные вернутся, прежде чем загорятся светодиоды. Однако производительность кода запроса может иметь значение, и Django ORM работает не слишком быстро ( но обычно достаточно быстро).
- Минимизируйте время установки / демонтажа. Иметь постоянно запущенный процесс и отправлять ему сообщения. (Поправьте меня, если я ошибаюсь, но именно на этом на самом деле сосредоточен ваш первоначальный вопрос.) Написан ли этот процесс на Python / Django или другом языке / фреймворке, как описано выше. Мне не нравится идея использовать команды управления так часто. Можно ли иметь постоянно работающий небольшой фрагмент кода, который отправляет сообщения от читателей NFC в очередь сообщений, которую Celery затем читает и пересылает в Django? Установка и демонтаж небольшой программы, даже если она написана на Python (но не Django!), Должна быть лучше, чем запуск и остановка программы Django (со всеми ее подсистемами).
Я не уверен, какой веб-сервер вы используете для Django. mod_wsgi
для Apache позволяет вам настроить количество процессов и потоков внутри процессов, которые запрашивает служба. Обязательно настройте соответствующую конфигурацию вашего веб-сервера, чтобы оптимизировать количество обслуживаемых запросов.
2. «Передача сообщений» с сигналами Джанго
Ваш второй вариант использования также довольно интересен; Я не уверен, что у меня есть ответы на это. Если вы удаляете экземпляры модели и хотите работать с ними позже, возможно, можно будет их сериализовать, JSON.dumps
а затем десериализовать JSON.loads
. Позже будет невозможно полностью воссоздать граф объектов (запрос связанных моделей), так как связанные поля лениво загружаются из базы данных, и эта ссылка больше не будет существовать.
Другой вариант заключается в том, чтобы каким-либо образом пометить объект для удаления и удалить его только в конце цикла запрос / ответ (после обслуживания всех сигналов). Это может потребовать специального сигнала для реализации этого, а не полагаться на post_delete
.