Как в Ruby on Rails сохранять объекты в памяти между сессиями? - PullRequest
16 голосов
/ 28 июля 2010

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

Предположим, например, что записи БД являются породами собак.Есть родительский класс Dog и дочерний класс для каждой породы.Фактические породы неизвестны до времени выполнения.

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

Почему бы просто не создать экземпляр на лету?В моем случае «собаки» - это в основном классы, которые содержат алгоритм и данные.Алгоритм не меняется, данные изменяются редко (порядка нескольких дней), но выполнение самого алгоритма, который использует как данные, так и некоторые динамические данные, передаваемые в виде временной метки, будет доступен несколько раз в секунду.

Было бы глупо заново создавать экземпляр объекта и загружать данные каждый раз, только чтобы выполнить запрос, а затем повторить его при следующем запросе (запросы не изменяют состояние объекта.объект).Я бы создавал и уничтожал несколько объектов в секунду, когда мог бы просто повторно использовать один и тот же объект.

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

Как мне сохранить эти объекты в памяти?Я в основном хочу таблицу поиска для хранения экземпляров.В Java я бы создал синглтон с неким типом хэш-карты или массива, который находится в памяти.В rails я попробовал это, создав одноэлементный класс в папке lib.Я думаю - я, возможно, не понимаю этого права - что экземпляр (тот факт, что это синглтон является спорным) теряется, когда сеанс исчезает.

Ближайший ответ, который я нашел, был http://www.ruby -forum.com / topic / 129372 , который в основном помещает все в поля и методы класса.Почему-то это не так.

TIA!

Дополнение: Я с Java.В Java я просто создал бы объект, который находится в куче или, может быть, в дереве JNDI, и, когда входили HTTP-запросы, они обрабатывались сервлетом, EJB или каким-либо элементом для каждого запроса, который затем мог получить доступ к постоянному объекту.Я не могу найти эквивалент в рельсах.

Ответы [ 5 ]

10 голосов
/ 28 июля 2010

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

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

class ObjectCache
  @@objects = {:beagle => Beagle.new, :poodle => Poodle.new}

  def lookup key
    @@objects[key.to_sym]
  end
end
6 голосов
/ 28 июля 2010

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

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

Сначала сравнительный тест, оптимизируйте только при необходимости.

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

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

0 голосов
/ 14 декабря 2011

Чтобы ваши классы не перезагружались при каждом запросе даже в режиме разработки, вы можете переместить их куда-нибудь за пределы путей автозагрузки (если используются значения по умолчанию за пределами каталогов app и lib).Таким образом, вы можете сохранить эти классы объектов между запросами и, следовательно, использовать их для хранения данных, одинаковых для каждого запроса.

0 голосов
/ 29 июля 2010

Да, классы также могут быть выгружены в режиме разработки. Это не только режим производства. Хотя это происходит по умолчанию в производственном режиме, где вы должны вручную установить его в режиме разработки.

0 голосов
/ 29 июля 2010

В производстве контроллеры и классы моделей не перезагружаются между запросами, поэтому у вас есть несколько вариантов:

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