<!--toc--> |
|
## Введение |
|
В CppCMS есть два основных ортогональных понятия: |
|
- **Приложения** - классы, наследуемые от `cppcms::application` - объекты, определяющие, как пользовательское приложение обрабатывает запросы. |
- **HTTP-контекст** - `cppcms::http::context` - контекст запроса, отклика, сессий сессии, кеша и многих других объектов, связанных с конкретным взаимодействием Клиент-Приложение. |
|
На каждый входящий запрос создается Контекст и ассоциируется с классом Приложения, который его обрабатывает. |
|
Когда запрос и отклик завершены, контекст |
уничтожается и приложение, обычно, продолжает |
работать. |
|
CppCMS создан для высокой производительности, поэтому "кэширует" все возможное. Это касается и объектов приложения. |
|
Прежде чем мы начнем, очень важно отличать два типа Приложений: |
|
1. **Синхронные Приложения** - наиболее распространенный тип приложений: обычные приложения, которые предназначены для обработки нормальных запросов. |
2. **Асинхронные Приложения** - специальные приложения, которые предназначены для обработки нескольких запросов и поддержки "long pooling". |
|
## Синхронные Приложения |
|
### Обособленное Приложение |
|
Синхронные приложения живут в пуле. Они генерируются специальным объектом `cppcms::applications_pool::factory`, "примонтированным" к объекту [`applications_pool`](/cppcms_ref_v0_99/classcppcms_1_1applications__pool.html). |
|
Эти объекты - долгоживущие и как только они созданы, как правило, кэшируются в пул для дальнейшего повторного использования. |
|
По входящему запросу приложение извлекается из пула или создается новое. Специальный объект `cppcms::http::context` назначается приложению на всю длительность обработки запроса. |
|
Этот запрос обрабатывается в потоковом пуле |
вызовом виртуальной функции `application::main()` |
, которая фактически обрабатывает запрос. |
|
После завершения запроса, этот контекст отсоединяется |
и приложение возвращается обратно в пул |
для дальнейшего повторного использования. |
|
Поэтому, когда Вы пишете собственные приложения, можете считать, |
что их конструкторы не вызываются часто. Вы должны также предполагать, что они будут "оставаться живыми" в течение длительного времени. |
|
Это хорошая идея, кэшировать некоторую общую, неизменяемую |
информацию в рамках такого объекта. |
|
### Приложения с дочерними приложениями |
|
У каждого приложения могут быть несколько дочерних, например: |
|
blog |
admin |
post_editing |
options_editing |
display |
post |
summary |
feeds |
atom |
rss |
|
|
Каждое дочернее приложение может быть соединено с родительским через |
члены-функции [`add` или `attach`](/cppcms_ref_v0_99/classcppcms_1_1application.html) |
в конструкторе. Каждое приложение разделяет свое время жизни и `cppcms::http::context` с родителем. |
|
Даже если они разных объектов и разных |
классов, они тесно связаны и живут |
вместе до тех пор, пока жив верхний родитель - `blog` в нашем случае. |
|
|
## Асинхронные Приложения |
|
### Время жизни |
|
В отличие от синхронных приложений, у которых несколько |
экземпляров в пуле преложений и выполняющихся |
экземпляров в пуле приложений и выполняющихся |
в потоковом пуле, асинхронные приложения |
предназначены для обаботки нескольких соединений |
предназначены для обработки нескольких соединений |
одновременно, и, таким образом, вместо того, чтобы вызываться |
в пуле потоков на каждый запрос, они работают исключительно |
в главном [цикле обработки событий CppCMS] (/ wikipp/ru/page/cppcms_1x_event_loop) |
в главном [цикле обработки событий CppCMS](/wikipp/ru/page/cppcms_1x_event_loop). |
|
Эти приложения живут до тех пор, как их счетчик ссылок не равен 0. |
Как только счетчик ссылок становится нулевым - приложение уничтожается и автоматически демонтируется из пула приложений. |
|
Поэтому, чтобы оставить асинхронное приложение живым, |
требуется выполнить одно из следующих действий: |
|
1. Держите постоянный smart-указатель `intrusive_ptr` |
указывающим на приложение, например |
в Вашей функции `main()`. |
|
Это подходит для длительных приложений, |
которые существуют в течение всего времени работы сервиса. |
|
2. Убедитесь, что у Вас есть обработчики событий, хранящие |
smart-указатель и ожидающие событие. |
|
Это обычно делается передачей `intrusive_ptr` |
в обработчик событий. |
|
Такой способ подходит для временных |
приложений, которые могут представлять, например, |
различные информационные каналы - такие как чаты |
, которые могут быть созданы или уничтожены |
различные информационные каналы - такие как чаты, |
которые могут быть созданы или уничтожены |
в некоторой точке. |
|
### Асинхронные приложения и их Дочерние приложения |
|
Каждое асинхронное приложение и его дети |
разделяют один и тот же счетчик ссылок. Таким образом, |
если дочернее приложение присоединено или назначено родителю, |
оно разделяет с ним свою ссылку и, например, |
передача smart-указателя в дочерний класс |
держит всю иерархию живой. |
|
Вобщем, по аналогии с синхронным приложением, |
родитель и все его предки "рождаются" и "умирают" вместе. |
|
### Обработка HTTP-Контекста |
|
Существует единственный контекст, назначенный асинхронному приложению. |
Если функция `cppcms::application::main()` завершается в то время, когда контекст все еще назначен, |
он будет автоматически отсоединен и будет завершен отклик клиенту. |
|
Для того, чтобы отложить отклик, контекст следует |
вручную отсоединить от приложения, вызовом функции |
`cppcms::application::release_context()`. |
|
Теперь это Ваша ответственность, держать его столько |
сколько нужно и завершить отклик вызовом |
`cppcms::http::context::complete_response()`. |