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

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

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

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

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

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

Заметки:

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

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

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

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

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

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

Совет. [После доработки]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

http://www.mems-exchange.org/software/durus/

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

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

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