- •Оглавление
- •Предисловие
- •Введение
- •Часть I Обзор Глава 1 "Расслоение" системы
- •Развитие модели слоев в корпоративных программных приложениях
- •Три основных слоя
- •Где должны функционировать слои
- •Глава 2 Организация бизнес-логики
- •Выбор типового решения
- •Глава 3 Объектные модели и реляционные базы данных
- •Архитектурные решения
- •Функциональные проблемы
- •Считывание данных
- •Взаимное отображение объектов и реляционных структур
- •Отображение связей
- •Наследование
- •Реализация отображения
- •Двойное отображение
- •Использование метаданных
- •Соединение с базой данных
- •Другие проблемы
- •Дополнительные источники информации
- •Глава 4 Представление данных в Web
- •Типовые решения представлений
- •Типовые решения входных контроллеров
- •Дополнительные источники информации
- •Глава 5 Управление параллельными заданиями
- •Проблемы параллелизма
- •Контексты выполнения
- •Изолированность и устойчивость данных
- •Стратегии блокирования
- •Предотвращение возможности несогласованного чтения данных
- •Разрешение взаимоблокировок
- •Транзакции
- •Типовые решения задачи обеспечения автономного параллелизма
- •Параллельные операции и серверы приложений
- •Дополнительные источники информации
- •Глава 6 Сеансы и состояния
- •В чем преимущество отсутствия "состояния"
- •Состояние сеанса
- •Глава 7 Стратегии распределенных вычислений
- •Соблазны модели распределенных объектов
- •Интерфейсы локального и удаленного вызова
- •Когда без распределения не обойтись
- •Сужение границ распределения
- •Интерфейсы распределения
- •Глава 8 Общая картина
- •Предметная область
- •Источник данных
- •Платформы и инструменты
- •Другие модели слоев
- •Часть II Типовые решения Глава 9 Представление бизнес-логики Сценарий транзакции (Transaction Script)
- •Модель предметной области (Domain Model)
- •Модуль таблицы (Table Module)
- •Слой служб (Service Layer)
- •Глава 10 Архитектурные типовые решения источников данных Шлюз таблицы данных (Table Data Gateway)
- •Шлюз записи данных (Row Data Gateway)
- •Активная запись (Active Record)
- •Преобразователь данных (Data Mapper)
- •Глава 11 Объектно-реляционные типовые решения, предназначенные для моделирования поведения Единица работы (Unit of Work)
- •Коллекция объектов (Identity Map)
- •Загрузка по требованию (Lazy Load)
- •Глава 12 Объектно-реляционные типовые решения, предназначенные для моделирования структуры Поле идентификации (Identity Field)
- •Отображение внешних ключей (Foreign Key Mapping)
- •Отображение с помощью таблицы ассоциаций (Association Table Mapping)
- •Отображение зависимых объектов (Dependent Mapping)
- •Внедренное значение (Embedded Value)
- •Сериализованный крупный объект (Serialized lob)
- •Наследование с одной таблицей (Single Table Inheritance)
- •Наследование с таблицами для каждого класса (Class Table Inheritance)
- •Наследование с таблицами для каждого конкретного класса (Concrete Table Inheritance)
- •Преобразователи наследования (Inheritance Mappers)
- •Глава 13 Типовые решения объектно-реляционного отображения с использованием метаданных Отображение метаданных (Metadata Mapping)
- •Объект запроса (Query Object)
- •Хранилище (Repository)
- •Глава 14 Типовые решения, предназначенные для представления данных в Web Модель-представление-контроллер (Model View Controller)
- •Контроллер страниц (Page Controller)
- •Контроллер запросов (Front Controller)
- •Представление по шаблону (Template View)
- •Представление с преобразованием (Transform View)
- •Двухэтапное представление (Two Step View)
- •Контроллер приложения (Application Controller)
- •Глава 15 Типовые решения распределенной обработки данных Интерфейс удаленного доступа (Remote Facade)
- •Объект переноса данных (Data Transfer Object)
- •Глава 16 Типовые решения для обработки задач автономного параллелизма Оптимистическая автономная блокировка (Optimistic Offline Lock)
- •Пессимистическая автономная блокировка (Pessimistic Offline Lock)
- •Блокировка с низкой степенью детализации (Coarse-Grained Lock)
- •Неявная блокировка (Implicit Lock)
- •Глава 17 Типовые решения для хранения состояния сеанса Сохранение состояния сеанса на стороне клиента (Client Session State)
- •Сохранение состояния сеанса на стороне сервера (Server Session State)
- •Сохранение состояния сеанса в базе данных (Database Session State)
- •Глава 18 Базовые типовые решения Шлюз (Gateway)
- •Преобразователь (Mapper)
- •Супертип слоя (Layer Supertype)
- •Отделенный интерфейс (Separated Interface)
- •Реестр (Registry)
- •Объект-значение (Value Object)
- •Деньги (Money)
- •Частный случай (Special Case)
- •Дополнительный модуль (Plugin)
- •Фиктивная служба (Service Stub)
- •Множество записей (Record Set)
- •Список типовых решений
- •Шпаргалка
- •Как управлять сложным потоком функций приложения?
- •Как взаимодействовать с базой данных?
- •Как избежать загрузки в оперативную память всего содержимого базы данных?
- •Как сохранить структуры наследования в реляционной базе данных?
Дополнительные источники информации
Эта глава только касается поверхности бездонного омута технологий управления параллельными операциями. Чтобы погрузиться глубже, понадобится более серьезная экипировка; в этом вам помогут книги [8,27, 36].
Глава 6 Сеансы и состояния
Различия между системными и бизнес-транзакциями уже рассматривались при обсуждении параллельного выполнения заданий (см. главу 5). Эти различия не только влияют на те или иные аспекты параллелизма, но и обусловливают способы сохранения в контексте транзакции информации временного характера, которая до определенного момента не может фиксироваться в базе данных.
Те же принципиальные различия лежат в основе многих дискуссий о роли и месте так называемых сеансов с сохранением промежуточного состояния (или, коротко говоря, сеансов "с состоянием") (stateful sessions) и сеансов "без состояния" (stateless sessions). По этому поводу сломано немало копий, но, как мне кажется, основная проблема нередко оказывается скрытой за частоколом сугубо технических вопросов. Необходимо понимать, что "состояние" является неотъемлемой частью сеансов определенных категорий и дальнейшие решения должны приниматься только с учетом этого факта.
В чем преимущество отсутствия "состояния"
Что подразумевается под сервером "без состояния"? Если говорить об объектах, то главное их достоинство состоит в том, что они сочетают в себе состояние (данные) и поведение (функции). Объект, лишенный состояния, — это объект без полей данных. Подобные объекты встречаются довольно редко, поскольку считается, что их наличие — признак плохого проектирования.
С другой стороны, однако, это явно не то, что думают многие, когда говорят об "отсутствии состояния" в объектах распределенных корпоративных приложений. Под сервером без состояния понимается объект, который просто не сохраняет данные между циклами обработки отдельных запросов. Подобный объект вполне способен содержать поля, но когда вызывается метод сервера без состояния, значения этих полей трактуются как неопределенные.
Примером сервера без состояния может служить система, в ответ на запрос возвращающая Web-страницу с информацией о книге. Пользователь задает код ISBN книги и активизирует объект ASP-документа или сервлета. Извлекая из базы данных информацию об авторе книги, ее наименовании и т.п., объект сервера может временно сохранять ее во внутренних полях, чтобы во всеоружии подойти к фазе генерации текста HTML. Объект также способен реализовать некоторую бизнес-логику, связанную, скажем, с определением того, какие дополнительные данные о книге следует предоставить пользователю. По завершении обработки запроса накопленная в полях объекта информация становится бесполезной. Очередной запрос с иным кодом ISBN — это, как говорится, совсем другая история. Поэтому поля такого объекта во избежание возможных ошибок инициируются заново.
Теперь вообразите, что ставится задача сбора сведений обо всех кодах ISBN, запрашиваемых клиентом с определенным IP-адресом. Информацию можно располагать в списке, поддерживаемом объектом сервера. В паузах между циклами обработки запросов список должен каким-то образом сохраняться, поэтому речь следует вести об объекте сервера "с состоянием". Переход от объекта без состояния к объекту с состоянием — это не просто замена предлога "без" предлогом "с". Многие воспринимают подобное требование едва ли не как катастрофу. Но почему?
Основная проблема связана с потребностью в ресурсах. Объекту сервера с состоянием необходимо сохранять все данные, образующие состояние, в период ожидания, пока пользователь предается тяжким раздумьям, "пялясь" в Web-страницу. Объект сервера без состояния, однако, в такой ситуации мог бы заняться обслуживанием запросов, инициируемых в других сеансах. Проведем далекий от реальности, тем не менее полезный мыслительный эксперимент. Представим, что сто человек интересуются книгами, упоминаемыми на страницах электронного каталога, и для обработки запроса по любой книге требуется одна секунда. Каждые 10 секунд каждый пользователь инициирует по одному запросу, и все запросы равномерно распределяются во времени. Если необходимо проследить историю запросов пользователей с помощью объектов сервера с состоянием, надлежит выделить по одному объекту для каждого пользователя, т.е. 100 объектов. Но 90% времени жизни объектов будет пропадать вхолостую. Отказавшись от намерений накопить сведения о читательских пристрастиях пользователей и решив применять объекты без состояния, способные просто обрабатывать запросы, можно обойтись всего десятью объектами сервера, которые будут заняты "делом" непрерывно.
Если в промежутках между вызовами методов данные не сохраняются, не имеет значения, каким именно объектом обслуживается запрос, но если состояние должно фиксироваться, обработкой запроса должен заниматься один и тот же объект. Отсутствие потребности в сохранении состояния дает возможность сформировать пул объектов, который позволит с меньшими затратами обслужить большее количество запросов. Чем больше пользователей-"тугодумов", тем выше ценность объектов сервера без состояния. Вполне очевидно, что особенно полезны объекты серверов без состояния, которые обслуживают Web-сайты с высоким уровнем трафика. Концепция объектов без состояния совершенно органично вписывается в модель Web, поскольку основной протокол Web, а именно HTTP, относится к категории протоколов без состояния.
Так что, никаких состояний — и точка, верно? Нет, если можно — пожалуйста. Но есть одна проблема: многие сценарии взаимодействия клиентов с сервером по своей природе предполагают сохранение состояния. Рассмотрим метафору "карты покупателя", лежащую в основе тысяч приложений электронной коммерции. В процессе общения с сайтом виртуального магазина (в данном случае книжного) посетитель формирует запросы и выбирает книги, которые желает приобрести. Карта покупателя должна сохраняться в течение всего пользовательского сеанса. По сути, речь идет о бизнес-транзакции с состоянием, которая может быть реализована посредством сеанса с состоянием. Если посетитель будет только пролистывать книги, но ничего так и не купит, его сеанс в этом частном случае лишится состояния, но стоит ему выбрать хотя бы одну книгу, данные о ней и определят состояние сеанса. Можно попытаться избежать необходимости сохранения информации состояния, но тогда придется существенно обеднить приложение; при выборе схемы с состоянием, напротив, нужно решать, как именно ее использовать. Хорошая новость заключается в том, что для реализации сеанса с состоянием, оказывается, можно применять сервер без состояния. Еще более любопытно, что такое решение не всегда в достаточной мере привлекательно.
