Как сделать объекты Python постоянными в веб-приложении? - PullRequest
6 голосов
/ 01 декабря 2008

Я пишу достаточно сложное веб-приложение. Бэкэнд Python запускает алгоритм, состояние которого зависит от данных, хранящихся в нескольких взаимосвязанных таблицах базы данных, которые меняются не часто, а также от пользовательских данных, которые часто меняются. Алгоритм каждого пользователя претерпевает множество небольших изменений по мере того, как пользователь работает с приложением. Этот алгоритм часто используется во время работы каждого пользователя для принятия определенных важных решений.

По соображениям производительности повторная инициализация состояния при каждом запросе (полунормализованных) данных базы данных быстро становится невозможной. Было бы весьма предпочтительно, например, кэшировать объект Python состояния каким-либо образом, чтобы его можно было просто использовать и / или обновлять при необходимости. Однако, поскольку это веб-приложение, существует несколько процессов, обслуживающих запросы, поэтому использование глобальной переменной исключено.

Я попытался сериализовать соответствующий объект (с помощью pickle) и сохранить сериализованные данные в БД, и сейчас я экспериментирую с кэшированием сериализованных данных через memcached. Тем не менее, это все еще имеет значительные накладные расходы на сериализацию и десериализацию объекта часто.

Я смотрел на решения с общей памятью, но единственное, что я нашел, это POSH . Однако POSH, похоже, не используется широко, и мне нелегко интегрировать такой экспериментальный компонент в мое приложение.

Мне нужен совет! Это мой первый шаг в разработке веб-приложения, поэтому я надеюсь, что это достаточно распространенная проблема, так как существуют известные решения таких проблем. На этом этапе достаточно решений, которые предполагают, что бэкэнд Python работает на одном сервере, но дополнительные баллы за решения, которые также масштабируются до нескольких серверов:)

Примечания:

  • У меня есть это приложение, работающее, в настоящее время живое и с активными пользователями. Я начал без какой-либо преждевременной оптимизации, а затем оптимизировал по мере необходимости. Я провел измерения и тестирование, чтобы убедиться, что вышеупомянутая проблема является фактическим узким местом. Я уверен, что уверен, что смогу выжать больше производительности из текущей настройки, но я хотел спросить, есть ли лучший способ.
  • Сама установка все еще находится в стадии разработки; Предположим, что архитектура системы может соответствовать вашему решению.

Ответы [ 6 ]

8 голосов
/ 01 декабря 2008

Будьте осторожны с преждевременной оптимизацией.

Добавление: «Бэкэнд Python запускает алгоритм, состояние которого ...» - это сеанс в веб-фреймворке. Вот и все. Позвольте платформе Django поддерживать состояние сеанса в кэше. Период.

«Состояние алгоритма для каждого пользователя претерпевает множество небольших изменений в процессе работы пользователя с приложением». Большинство веб-фреймворков предлагают кэшированный объект сеанса. Часто это очень высокая производительность. Для этого смотрите документацию сессии Django .

Совет. [Пересмотренный]

Кажется, у вас есть что-то, что работает. Используйте, чтобы изучить свою структуру, изучить инструменты и узнать, какие ручки вы можете повернуть, не потревожив. В частности, используя состояние сеанса.

Во-вторых, возитесь с кешированием, управлением сессиями и другими вещами, которые легко настроить, и посмотрите, достаточно ли у вас скорости. Узнайте, работает ли сокет MySQL или именованный канал быстрее, попробовав их. Это оптимизация без программирования.

В-третьих, измерьте производительность, чтобы найти фактическое узкое место. Будьте готовы предоставить (и защитить) измерения как достаточно мелкозернистые, чтобы быть полезными и достаточно стабильными для обеспечения значимого сравнения альтернатив.

Например, показать разницу в производительности между постоянными и кэшированными сеансами.

3 голосов
/ 01 декабря 2008

Я думаю, что многопроцессорная инфраструктура имеет то, что может быть применимо здесь, а именно - модуль общих ctypes.

Многопроцессорность является довольно новым для Python, поэтому она может иметь некоторые странности. Я не совсем уверен, работает ли решение с процессами, не порожденными через multiprocessing.

2 голосов
/ 17 мая 2009

Это Durus, постоянная объектная система для приложений, написанных на Python. язык программирования. Durus предлагает простой способ использования и поддержания последовательной коллекция экземпляров объектов, используемых одним или несколькими процессами. Доступ и изменение постоянные экземпляры управляются через кэшированный экземпляр подключения, который включает методы commit () и abort (), чтобы изменения были транзакционными.

http://www.mems -exchange.org / Программное обеспечение / Durus /

Я использовал его раньше в каком-то исследовательском коде, где хотел сохранить результаты некоторых вычислений. В конце концов я переключился на pytables , так как он лучше отвечал моим потребностям.

2 голосов
/ 01 декабря 2008

Прежде всего, ваш подход не является обычной практикой веб-разработки. Даже при использовании многопоточности веб-приложения рассчитаны на работу в многопроцессорных средах, обеспечивая как масштабируемость, так и простоту развертывания.

Если вам нужно просто инициализировать большой объект, и вам не нужно вносить изменения позже, вы можете легко это сделать, используя глобальную переменную, которая инициализируется во время создания вашего приложения WSGI, или модуль содержит объект, который находится загруженный и т. д., мульти обработка будет хорошо для вас.

Если вам нужно изменить объект и получить к нему доступ из каждого потока, вы должны быть уверены, что ваш объект является потокобезопасным, для этого используйте блокировки. И использовать один контекст сервера, процесс. Любой многопоточный сервер Python будет вам полезен, также FCGI - хороший выбор для такого дизайна.

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

2 голосов
/ 01 декабря 2008

Я думаю, вы можете дать ZODB шанс.

"Главная особенность ZODB - прозрачность. Вам не нужно писать какой-либо код для явного чтения или записи ваших объектов в базу данных или из нее. Вы просто помещаете свои постоянные объекты в контейнер, который работает так же, как словарь Python. Все, что находится внутри этого словаря, сохраняется в базе данных. Этот словарь называется «корнем» базы данных. Это похоже на волшебный пакет, любой объект Python, который вы помещаете в него, становится постоянным. "

Изначально это была неотъемлемая часть Zope, но в последнее время также доступен автономный пакет.

Имеет следующее ограничение:

"На самом деле есть несколько ограничений на то, что вы можете хранить в ZODB. Вы можете хранить любые объекты, которые можно« протравить », в стандартном кроссплатформенном последовательном формате. Такие объекты, как списки, словари и числа могут быть Объекты, такие как файлы, сокеты и объекты кода Python, не могут быть сохранены в базе данных, поскольку они не могут быть обработаны. "

Я прочитал это, но сам не сделал этого.

Другая возможная вещь может быть sqlite db в памяти, которая может немного ускорить процесс - быть db в памяти, но все же вам придется выполнять сериализацию и все такое. Примечание: в памяти дБ стоит дорого по ресурсам.

Вот ссылка: http://www.zope.org/Documentation/Articles/ZODB1

1 голос
/ 01 декабря 2008

Другой вариант - пересмотреть требование к состоянию, похоже, что если сериализация - это горлышко бутылки, тогда объект очень большой. Вам действительно нужен такой большой объект?

Я знаю, что в подкасте Stackoverflow 27 ребята из Reddit обсуждают, что они используют для состояния, так что это может быть полезно для прослушивания.

...