Жизненный цикл приложения
Введение
В CppCMS есть два основных ортогональных понятия:
- Приложения - классы, наследуемые от
cppcms::application
- объекты, определяющие, как пользовательское приложение обрабатывает запросы. - HTTP-контекст -
cppcms::http::context
- контекст запроса, отклика, сессий сессии, кеша и многих других объектов, связанных с конкретным взаимодействием Клиент-Приложение.
На каждый входящий запрос создается Контекст и ассоциируется с классом Приложения, который его обрабатывает.
Когда запрос и отклик завершены, контекст уничтожается и приложение, обычно, продолжает работать.
CppCMS создан для высокой производительности, поэтому "кэширует" все возможное. Это касается и объектов приложения.
Прежде чем мы начнем, очень важно отличать два типа Приложений:
- Синхронные Приложения - наиболее распространенный тип приложений: обычные приложения, которые предназначены для обработки нормальных запросов.
- Асинхронные Приложения - специальные приложения, которые предназначены для обработки нескольких запросов и поддержки "long pooling".
Синхронные Приложения
Обособленное Приложение
Синхронные приложения живут в пуле. Они генерируются специальным объектом cppcms::applications_pool::factory
, "примонтированным" к объекту applications_pool
.
Эти объекты - долгоживущие и как только они созданы, как правило, кэшируются в пул для дальнейшего повторного использования.
По входящему запросу приложение извлекается из пула или создается новое. Специальный объект cppcms::http::context
назначается приложению на всю длительность обработки запроса.
Этот запрос обрабатывается в потоковом пуле
вызовом виртуальной функции application::main()
, которая фактически обрабатывает запрос.
После завершения запроса, этот контекст отсоединяется и приложение возвращается обратно в пул для дальнейшего повторного использования.
Поэтому, когда Вы пишете собственные приложения, можете считать, что их конструкторы не вызываются часто. Вы должны также предполагать, что они будут "оставаться живыми" в течение длительного времени.
Это хорошая идея, кэшировать некоторую общую, неизменяемую информацию в рамках такого объекта.
Приложения с дочерними приложениями
У каждого приложения могут быть несколько дочерних, например:
blog admin post_editing options_editing display post summary feeds atom rss
Каждое дочернее приложение может быть соединено с родительским через
члены-функции add
или attach
в конструкторе. Каждое приложение разделяет свое время жизни и cppcms::http::context
с родителем.
Даже если они разных объектов и разных
классов, они тесно связаны и живут
вместе до тех пор, пока жив верхний родитель - blog
в нашем случае.
Асинхронные Приложения
Время жизни
В отличие от синхронных приложений, у которых несколько экземпляров в пуле приложений и выполняющихся в потоковом пуле, асинхронные приложения предназначены для обработки нескольких соединений одновременно, и, таким образом, вместо того, чтобы вызываться в пуле потоков на каждый запрос, они работают исключительно в главном цикле обработки событий CppCMS.
Эти приложения живут до тех пор, как их счетчик ссылок не равен 0. Как только счетчик ссылок становится нулевым - приложение уничтожается и автоматически демонтируется из пула приложений.
Поэтому, чтобы оставить асинхронное приложение живым, требуется выполнить одно из следующих действий:
Держите постоянный smart-указатель
intrusive_ptr
указывающим на приложение, например в Вашей функцииmain()
.Это подходит для длительных приложений, которые существуют в течение всего времени работы сервиса.
Убедитесь, что у Вас есть обработчики событий, хранящие smart-указатель и ожидающие событие.
Это обычно делается передачей
intrusive_ptr
в обработчик событий.Такой способ подходит для временных приложений, которые могут представлять, например, различные информационные каналы - такие как чаты, которые могут быть созданы или уничтожены в некоторой точке.
Асинхронные приложения и их Дочерние приложения
Каждое асинхронное приложение и его дети разделяют один и тот же счетчик ссылок. Таким образом, если дочернее приложение присоединено или назначено родителю, оно разделяет с ним свою ссылку и, например, передача smart-указателя в дочерний класс держит всю иерархию живой.
Вобщем, по аналогии с синхронным приложением, родитель и все его предки "рождаются" и "умирают" вместе.
Обработка HTTP-Контекста
Существует единственный контекст, назначенный асинхронному приложению.
Если функция cppcms::application::main()
завершается в то время, когда контекст все еще назначен,
он будет автоматически отсоединен и будет завершен отклик клиенту.
Для того, чтобы отложить отклик, контекст следует
вручную отсоединить от приложения, вызовом функции
cppcms::application::release_context()
.
Теперь это Ваша ответственность, держать его столько
сколько нужно и завершить отклик вызовом
cppcms::http::context::complete_response()
.