На главную

Библиотека Интернет Индустрии I2R.ru

Rambler's Top100

Малобюджетные сайты...

Продвижение веб-сайта...

Контент и авторское право...

Забобрить эту страницу! Забобрить! Блог Библиотека Сайтостроительства на toodoo
  Поиск:   
Рассылки для занятых...»

Компоненты ASP. Службы COM+ в ASP-компонентах и ASP-приложениях

04.06.2004 18:10

Создавать и успешно использовать ASP-компоненты можно и без прямого обращения к каким-либо службам COM+. Однако именно эти службы могут внести ту "изюминку", которая превратит просто удовлетворительно работающее ASP-приложение в хорошо масштабируемое и соответствующее предъявляемым ему требованиям, независимо от того, каковы эти требования.

Службы COM+, к которым, прежде всего, стоит обратиться в разработке ASP-компонентов, - это управление транзакциями (transaction management), активация по требованию (just-in-time activation, JIT) и резервирование (pooling). Кроме того, можно использовать новые интерфейсы, которые были созданы для поддержания большей части возможностей этих служб. Однако перед рассмотрением всех этих новшеств обратимся к применению компонентов в приложениях.

Разработка систем на основе компонентов

Именно система, построенная на основе компонентов, выделяет индивидуальные процессы в многократно используемые порции кода и данных, а затем использует один или несколько этих компонентов для сознания полноценных приложений. Среди нескольких типов приложений различают клиент-серверную (client/server), распределенную (distributed) и многоярусную (n-tier) системы. В клиент-серверной системе (client-server system) процессы распределяются между клиентом и сервером, причем клиент отвечает за все взаимодействия с пользователем, отображение данных и подтверждение полномочий клиента, а сервер обрабатывает большую часть обращений к базам данных, проверяет полномочия сервера и контролирует бизнес-правила. В распределенной системе (distributed system) компоненты приложений могут располагаться на разных машинах и географически находиться в разных местах. Кроме того, для обработки множественных запросов может быть создано несколько экземпляров одного и того же компонента, таким образом, появляется возможность предоставлять одну и ту же услугу сразу множеству клиентов. И наконец, многослойная система (n-tier system) объединяет в себе элементы как клиент-серверной, так и распределенной систем. Здесь, как и в клиент-серверной системе, присутствует иерархия компонентов, однако сами по себе компоненты могут дублироваться для распределения загрузки процессов, а также распределяться на большом количестве машин и мест, как это происходит в распределенной системе. Стандартная n-ярусная система может состоять из клиента, выполняющего все взаимодействия с пользователем, проверку полномочий клиента и отображение данных; бизнес-уровня, контролирующего бизнес-правила, общие вопросы управления транзакциями и проверку полномочий, и уровня данных, обрабатывающего все прямые обращения к данным.

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

Другим преимуществом компонентов является тот факт, что гораздо больше родовых функций (generic functions) может быть разделено на отдельные компоненты и, таким образом, использовано во всей системе. Кроме того, применение компонентов упрощает модель и конструкцию n-ярусной системы. В качестве примера можно привести систему, в которой интерфейсный компонент проверяет достоверность адресной информации. Проверка достоверности достаточно характерна: она просто подтверждает тот факт, что все необходимые поля, такие как "Город" или "Почтовый индекс", заполнены. Тогда бизнес-уровень сможет обрабатывать для приложения адресную информацию, исходя из типа бизнеса. На основе адресной информации бизнес-уровень может вести поиск, например, зон отгрузки для компонента с помощью соответствующего приложения или зон доставки для виртуальной системы заказов. Компонент может обратиться к уровню данных для сохранения адресной информации, извлечения дополнительной информации или даже для запуска других виртуальных бизнес-компонентов, выполняющих какую-либо еще обработку информации. Уровень данных сам по себе может быть разделен по отдельным машинам, отдельным базам данных или даже различным типам хранилищ данных, вместе с некоторой информацией, идущей на долговременное или кратковременное хранение (если информация может потребоваться лишь в некоторой специфической задаче, а затем должна быть удалена).

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

ASP-компоненты принимают активное участие в этом типе систем, обеспечивая работу бизнес-уровня или уровня данных. Интерфейс пользователя при этом поддерживается браузером, обращающимся к ASP-приложению.

В Windows 2000 работа с компонентами существенно облегчается службами COM+, выполняющими для компонентов такие действия, как например резервирование и транзакции. Именно для реализации этих задач традиционные интерфейсы COM были дополнены совершенно новыми интерфейсами, о которых вы узнаете в следующем разделе.

Интерфейсы COM+

Большинство важнейших интерфейсов COM, таких как, например, IUnknown и IDispatch, с появлением среды COM+ не претерпело каких-либо изменений и по сию пору решает все те же знакомые нам задачи. Главное отличие между COM и COM+ состоит в том, что та функциональность, которая в Windows NT и Windows 98 выполнялась средствами MTS, нынче полностью интегрирована в архитектуру COM+. Такого рода интеграция не только принесла с собой новые возможности, предоставляемые службами COM+, но и позволила существенно улучшить характеристики компонентов.

Разумеется, разработчики COM+ не забыли о необходимости поддержки новых служб COM+, а также нескольких новых интерфейсов уже имеющимися средствами, реализованными в MTS. В следующих нескольких разделах нами будут рассмотрены несколько ключевых интерфейсов, без знания которых, как нам кажется, разработка ASP-компонентов была бы бессмысленна.

Интерфейс IObjectContext

В главе 4 мы обсуждали концепцию контекстов (contexts) как совокупностей объектов, отвечающих одинаковыми требованиями. Среди таких требований может быть, например, возможность резервирования (pooling) для компонентов или их совместное участие в транзакциях.

В Windows 2000 контекст компонентов представляет собой набор свойств времени выполнения (runtime properties), непосредственная работа с которым может вестись с помощью объекта ObjectContext, управляющего контекстной информацией для компонента. Для доступа к свойствам объекта ObjectContext используется интерфейс IObjectContext, доступный, в свою очередь, с помощью библиотеки типов служб COM+.

Ответ на вопрос о том, каким именно образом осуществляется доступ к объекту ObjectContext, зависит от того, каким языком программирования вы пользуетесь. Например, если взять Visual Basic, то здесь сначала производится импорт ссылки на библиотеку типов служб COM+ в рабочий проект, и только потом можно создать ссылку на объект ObjectContext и вызвать для создания экземпляра метод GetObjectContext:

Dim objContext As ObjectContext
Set objContext = GetObjectContext

В Visual С++ под Windows NT для доступа к объекту ObjectContext также можно применить метод GetObjectContext:

CComPtr<IObjectContext> m_spObjectContext;
hr = GetObjectContext(&m_spObjectContext);

В то же время, в Visual C++ под Windows 2000 для передачи интерфейсу идентификатора GUID уже используется метод CoGetObjectContext:

hr = CoGetObjectContext(IID_IObjectContextInfo,
         (void **)&m_spObjectContext);

Независимо от того, применяется ли метод GetObjectContext или метод CoGetObjectContext, результаты будут одними и теми же, поскольку вызов метода CoGetObjectContext в COM+ является оболочкой для вызова метода GetObjectContext. В Visual С++ придется также добавить в путь библиотеки компонента ссылку на заголовочный файл comsvcs.h служб COM+ и ссылку на файл связанного объекта comsvcs.lib.

Получив ссылку на интерфейс IObjectContext, можно вызывать его методы, перечисленные в табл. 1.

табл. 1. Методы интерфейса IObjectContext

Метод Описание
CreateInstance Создает экземпляр объекта
DisableCommit Показывает, что компонент не готов к выполнению транзакции
EnableCommit Показывает, что компонент все еще обрабатывается, но транзакция может быть выполнена
IsCallerInRole Показывает, соответствует ли вызывающий определенной роли (с учетом ролевой безопасности)
IsInTransaction Показывает, участвует ли компонент в транзакции
IsSecurityEnabled Показывает, включена ли защита
SetAbort Показывает, что компонент завершил работу и транзакция прервана
SetComplete Показывает, что компонент завершил работу и транзакция готова к принятию

Интерфейс обладает следующими свойствами:

  • ContextInfo - возвращает ссылку на объект контекстной информации, связанный с компонентом;
  • Count - показывает число именованных свойств объекта;
  • Item - содержит имена свойств;
  • Security - возвращает ссылку на объект Security, связанный с объектом ObjectContext.

Интерфейс информации контекста IObjectContextInfo более подробно будет рассмотрен в следующем разделе. Для обращения к встроенным ASP-объектам применяется коллекция Item. Получить доступ к ней можно непосредственно из Visual Basic:

Dim oc As ObjectContext
Dim app As Application
Set oc = GetObjectConext
Set app = oc.Item("Application")

Получить доступ к ASP-объектам можно и через объект ObjectContext:

Set app = oc("Application")

Из других программных языков для обращения к объектам ASP придется применить другие технологии. В C++, например, для получения доступа к определенному ASP-объекту нужно послать запрос экземпляру интерфейса IGetContextProperties:

CComPtr<IGetContextProperties> pProps; //свойства контекста

//получение ObjectContext
hr = CoGetObjectContext(IID_IObjectContext,
   (void **)&m_spObjectContext);
if (FAILED(hr)) return hr;

//получение свойств контекста
  hr = m_spObjectContext ->
  QueryInterface( IID_IGetContextProperties,
                 (void**)&pProps );
if (FAILED(hr)) return hr;

получение свойства Response
bstrProp = "Response";
hr = pProps->GetProperty( bstrProp, &vt ) ;
if (FAILED(hr)) return hr;

piDispatch = vt. pdispVal;
hr = piDispatch->QueryInterface( IID_IResponse,
   (void**)&m_piResponse );

В документации к интерфейсу IGetContextProperties сообщается, что он действует только в среде Windows NT, но и в Windows 2000 с его помощью также можно обращаться к встроенным ASP-объектам.

Интерфейс IObjectContextInfo

Интерфейс IObjectContextInfo служит для получения относящейся к текущему компоненту информации о транзакциях, активности и контексте. С помощью этого интерфейса можно получить доступ к указателю на интерфейс ITransaction. В табл. 2 приведены методы интерфейса IObjectContextInfo.

табл. 2. Методы интерфейса IObjectContextInfo

Метод Описание
GetActivityId Возвращает идентификатор текущей активности
GetContextId Возвращает идентификатор текущего контекста
GetTransaction Возвращает указатель на интерфейс ITransaction
GetTransactionId Возвращает идентификатор текущей транзакции
IsInTransaction Показывает, участвует ли компонент в транзакции

Если в компонентах COM+ осуществляется синхронизация (описываемая позже), метод GetActivityId возвращает идентификатор текущей активности, в противном случае будет возвращено значение Null.

Метод GetTransaction возвращает указатель на интерфейс ITransaction. С помощью этого интерфейса можно принять или прервать транзакцию, хотя реализуются эти функции с помощью объекта ObjectContext или интерфейса IContextState, рассматриваемых далее.

Интерфейс IContextState

Интерфейс IContextState предоставляет возможность более четкого управления транзакциями и активацией, чем это допустимо в интерфейсе IObjectContext. Например, в интерфейсе IObjectContext с помощью метода SetComplete можно отметить компонент, как завершивший работу и ожидающий принятия транзакции, а с помощью метода SetAbort отметить его как завершивший работу и ожидающий прерывания текущей транзакции.

На практике есть два условных бита, устанавливаемых при работе с методами SetComplete и SetAbort. Первый из их - бит завершения (done bit), его установка указывает COM+, что обработка компонента завершена. Второй - бит согласованности (consistency bit). Установка этого бита определяет, может ли быть транзакция принята или она должна быть прервана.

Оба метода, SetComplete и SetAbort, интерфейса IObjectContext одновременно устанавливают оба бита, причем оба устанавливают бит завершения в значение True, указывая, что обработка компонента завершена. В то же время, с помощью интерфейса IContextState можно идентифицировать факт окончания работы компонента отдельно от статуса транзакции.

В табл. 3 приведены четыре метода интерфейса IContextState.

табл. 3. Методы интерфейса IContextState

Метод Описание
GetDeactivateOnReturn Получает состояние бита завершения
GetMyTransactionVote Получает состояние бита согласованности
SetDeactivateOnReturn Сигнализирует о завершении работы компонента
SetMyTransactionVote Идентифицирует возможность принятия либо прерывания транзакции

Бит завершения можно получать и устанавливать с помощью методов SetDeactivateOnReturn и GetDeactivateOnReturn. Компонент деактивируется по завершении методов только при значении бита завершения, установленном в True.

Чтобы убедиться во всех этих возможностях, создайте компонент Visual Basic, реализующий для перехвата событий JIT интерфейс IObjectControl. (Интерфейс IObjectControl подробно описывается в следующем разделе.) У этого метода будет два компонента, каждый из которых вызывает метод SetDeactivateOnReturn интерфейса IContextState. Первая функция будет вызывать метод, передавая логическое значение False, вторая - True.

Создайте проект Visual Basic и назовите его asp0501, а класс генерируемого компонента - done. Присоедините к проекту библиотеки типов служб COM+ и Microsoft Active Server Pages. Коль скоро библиотеки типов добавлены как ресурсы, реализуйте, как показано в листинге 5.1, JIT-методы Activate, Deactivate и CanBePooled интерфейса IObjectControl.

Листинг 1. Реализация JIT-функций интерфейса IObjectControl

Implements ObjectControl

Dim objResponse As Response

Private Sub ObjectControl_Activate()
Set objResponse = GetObjectContext().Item("Response")
objResponse.Write "<h3>Активирован</h3>"
End Sub

Private Sub ObjectControl_Deactivate()
objResponse.Write "<h3>Деактивирован</h3>"
Set objResponse = Nothing
End Sub

Private Function ObjectControl_CanBePooled() As Boolean
     ObjectControl_CanBePooled = False
End Function

В методе Activate созданная ссылка на встроенный ASP-объект Response используется для отображения сообщения о том, что метод активирован. В методе Deactivate на web-страницу выводится сообщение о том, что компонент деактивирован.

Далее, добавьте две функции компонента, вызываемые ASP-страницей. Первая, под именем function1, обращается к интерфейсу IContextState и вызывает его метод SetDeactivateOnReturn, передавая значение False. Вторая функция, function2, также вызывает метод SetDeactivateOnReturn, но на сей раз передается значение True. В листинге 5.2 приведен программный код обеих функций, который и нужно добавить к нашему компоненту.

Листинг 2. Подпрограммы, вызывающие метод SetDeactivateOnReturn

Sub function1()

Dim iCntxt As IContextState
Set iCntxt = GetObjectContext

iCntxt.SetDeactivateOnReturn False
End Sub

Sub function2()

Dim iCntxt As IContextState
Set iCntxt = GetObjectContext

iCntxt.SetDeactivateOnReturn True
End Sub

После того как проект компонента скомпилирован и добавлен к приложению COM+, протестируйте новый компонент с помощью ASP-сценария примерно такого содержания (как в странице asp0501.asp):

<%
Dim obj
Set obj = Server.CreateObject("asp0501.done")

Response.Write "Вызов function 2" & "<br>"

obj.function2

Response.Write "Вызов function 1" & "<br>"

obj.function1

Response.Write "Вызов function 2" & "<br>"

obj.function2
%>

Первой вызывается функция function2, деактивирующая компонент при возвращении значения функцией. Благодаря этому при обращении к функции компонента будет отображаться сообщение "Активирован", а при возвращении функцией значения будет отображаться сообщение "Деактивирован" еще до сообщения "Вызов function 1".

Следует заметить, что при вызове первой функции, не деактивирующей компонент, сообщение "Деактивирован" при возвращении функцией значения не появится.

Наконец, при повторном вызове функции function2, должны быть отображены оба сообщения, "Активирован" и "Деактивирован", при этом генерируется web-страница со следующими сообщениями:

Вызов function 2

Активирован

Деактивирован

Вызов function 1

Активирован

Вызов function 2

Деактивирован

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

Интерфейс IObjectControl

В этом разделе показано, как можно управлять временем жизни (lifetime) компонента с помощью интерфейса IContextState. В примере также используется активация по требованию (just-in-time activation, JIT) - для управления созданием экземпляра компонента и записи на web-страницу с помощью методов Activate и Deactivate интерфейса IObjectControl сообщений об активации и деактивации компонента.

Разрешение активации по требованию компонента означает, что компонент активируется, только когда он реально требуется, а не при первоначальном создании на ASP-странице. Кроме того, компонент деактивируется, только когда он помечается как готовый к деактивации, удаляется внутри ASP-страницы (например, установлен в Nothing, если вы работаете с VBScript) или процесс выходит за пределы страницы.

Процесс активации и деактивации управляется COM+ с помощью программных ключей, указываемых разработчиками, как, например, тот, что показан в этом разделе для вызова метода SetDeactivateOnReturn интерфейса IContextState.

Как разработчик компонента, вы можете перехватывать моменты активации и деактивации компонента путем реализации методов Activate и Deactivate интерфейса IObjectControl. В этом случае вы не зависите от ресурсов (типа ссылки на объект Response в листинге 5.1) в период простоя компонента и ожидания вызова его методов.

При реализации интерфейса IObjectControl вы должны реализовать и методы Activate и Deactivate - а кроме того, еще и метод CanBePooled. Этот последний метод определяет, находится ли компонент в состоянии, когда он может быть резервирован (pooled). Позднее в этой главе при описании служб COM+ мы рассмотрим резервирование (pooling) компонентов более подробно.

Чтобы воспользоваться преимуществами активации по требованию, компонент должен быть установлен в приложение COM+, а активация по требованию разрешена. Впрочем, поддержка активации по требованию в приложении COM+ для всех компонентов включена по умолчанию.

Интерфейсы IObjectControl и IObjectContext были реализованы в Windows NT и управляются посредством MTS. Фактически же, ASP-компоненты, созданные для Windows NT, за исключением использующих специфические службы NT, можно без проблем перенести на Windows 2000 и COM+, что и обсуждается в следующем разделе.

ПРИМЕЧАНИЕ
В Windows NT приходилось избегать применения обработчиков событий Initialize и Terminate, поскольку они не позволяли обратиться к экземпляру объекта ObjectContext. Это ограничение в Windows 2000 снято. И все же, по-прежнему важно рассмотреть реализацию интерфейса IObjectControl и перехват (trapping) событий Activate и Deactivate для обеспечения доступа к глобальным ресурсам и их высвобождения.

Перенос пакетов MTS в приложения COM+

В Windows NT (or Windows 9x) компонентами можно было управлять как частью пакетов (packages) MTS. Будучи частью пакета MTS, компонент мог воспользоваться некоторыми возможностями MTS, например, выполнением транзакций и активацией по требованию. Те же и многие другие возможности доступны также и в COM+, и обратиться к ним из существующих компонентов можно, перенеся в новую среду пакеты MTS, компоненты или то и другое.

Для переноса существующего пакета MTS нужно, прежде всего, экспортировать пакет в файл с расширением .pak (файл пакета MTS). Это можно сделать, щелкнув правой кнопкой мыши на существующем приложении MTS и выбрав в меню команду Export (Экспорт). Далее нужно просто следовать указаниям по экспорту в файл пакета MTS, решив, в том числе, вопрос об экспорте ролей вместе с пакетом.

Можно относительно просто перенести пакеты MTS в COM+, создав с помощью консоли служб компонентов (Component Services Console) новое приложение COM+ и установив переключатель Install Pre-built Application(s) (Установить готовое приложение). Когда мастер установки приложения COM (COM Application Install Wizard) запросит имя существующего приложения, найдите или выберите созданный ранее PAK-файл.

При импорте существующего пакета MTS в новое приложение COM+ диспетчер служб компонентов (Component Services Manager) импортирует также роли (roles) и пытается сопоставить существующую функциональность MTS новой функциональности служб COM+ - включая настройки транзакций и активации по требованию.

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

В следующем разделе обсуждаются некоторые настройки приложений COM+, влияющие на ASP-приложения.

СОВЕТ
За дополнительной информацией о работе с консолью служб компонентов (Component Services Console) обратитесь к справочной системе Windows 2000.

Активация приложений COM+

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

ПРИМЕЧАНИЕ
В этом разделе рассмотрены не все возможные службы COM+, а лишь самые необходимые для разработки ASP-компонентов, например, безопасность, транзакции и объединение объектов. Активация по требованию подробно рассмотрена в разделе "Интерфейс IObjectControl".

Безопасность приложений

Управлять безопасностью ASP-приложения на уровне страницы или ресурса можно с помощью средств безопасности NTFS или средств безопасности IIS. С помощью средств ролевой безопасности приложений COM+ можно добавить и еще один уровень безопасности.

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

Приложение COM+ можно создать по двум различным схемам активации: активации внутри клиентского процесса и активации в изолированном процессе.

Если приложение COM+ создано как серверное, обращение к компоненту с ASP-страницы генерирует отдельную программу dllhost.exe для этого компонента и любого другого, являющегося частью приложения COM+. Поскольку компонент находится в отдельном процессе, все вызовы компонента с ASP-страницы должны маршализироваться. Вместе с тем, если компонент некачественный и генерирует нечто опасное для программного обеспечения, это нечто останется внутри файла dllhost.exe и не сможет неблагоприятно повлиять на IIS или остальные ASP-приложения.

Если создать приложение COM+ как библиотечное, при обращении к компоненту с ASP-страницы экземпляр этого компонента (и любого другого внутри приложения COM+) создается внутри того же процесса, что и ASP-страница - если только поточная модель компонента совместима. Поскольку приложения COM+ допускают апартаментно-поточную, произвольно-поточную и нейтрально-поточную модели, экземпляр компонента приложения COM+ должен создаваться внутри процесса ASP-страницы, а все вызовы между сценарием страницы и компонентом должны выполняться в том же потоке.

Службы COM+

Компонент, с помощью диспетчера служб COM+ (COM+ Services Manager) установленный как часть приложения COM+, называется сконфигурированным компонентом (configured component). Такой компонент может воспользоваться преимуществами служб COM+, например, поддержкой транзакций и активацией по требованию. Компонент, не установленный как часть приложения COM+ и зарегистрированный с помощью инструментов разработки (например, VB) или утилиты regsvr32.exe, называется несконфигурированным компонентом (unconfigured component). Этот тип компонента использовать в ASP-приложениях можно, но реализовать интерфейс IObjectControl, воспользоваться преимуществами активации по требованию или применить объект ObjectContext для поддержки транзакций нельзя. Можно, однако, как и прежде, обратиться с помощью объекта ObjectContext к встроенным объектам ASP.

Одним из основных доводов в пользу добавления компонента в приложение COM+ является желание применить компонент в транзакциях. Это момент обсуждается в следующем разделе.

Поддержка транзакций

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

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

Кроме того, MTS предоставляет менеджеров (managers) и диспетчеров (dispensers) ресурсов, которые управляют данными хранилищ, например, данными баз данных. По сути, любая система баз данных, поддерживающая транзакции OLE, скажем, SQL Server, может участвовать в транзакциях, управляемых MTS. Это означает, что если компонент, участвующий в транзакции, выполняется с ошибкой, то можно отозвать (вернуть к прежнему состоянию) не только его действия и действия других компонентов, но и любое действие, произведенное базой данных.

Все возможности MTS по работе с транзакциями реализованы в службах COM+ и доступны для сконфигурированных компонентов. Отличие состоит в том, что в COM+ (и Windows 2000) присутствует интерфейс IContextState, позволяющий отделить активацию компонента от управления транзакциями. Этот интерфейс способен сигнализировать, собирается ли компонент принять или прервать транзакцию, при этом компонент остается активированным, как было ранее показано в листинге 5.1.

Что такое транзакции?

Если вы имели опыт работы с коммерческими базами данных, например, с Oracle, Sybase и Microsoft SQL Server, то, возможно, знаете, что представляют собой транзакции. Транзакция (transaction) - это одна или несколько задач, некоторым образом логически сгруппированных, причем все задачи, объединенные в данную группу, либо все вместе успешно завершаются, либо все вместе не выполняются, если хотя бы одна из задач внутри транзакции не выполнена. Если транзакция не состоялась, никаких изменений данных, связанных с данной транзакцией, не делается. Если же выполнение транзакции происходит успешно, все изменения данных принимаются. В качестве примера транзакции с несколькими задачами можно привести перевод денег со сберегательного на расчетный счет. Хотя это и похоже на одну транзакцию, в действительности, происходят сразу две транзакции. Первая транзакция состоит в снятии ваших денег со сберегательного счета (то есть они дебетуются на счет), вторая транзакция заключается в переведении этих денег на расчетный счет (то есть они кредитуются на расчетный счет) . Если операция снятия денег со сберегательного счета прошла успешно, а операция по переводу денег на расчетный счет не была выполнена, вы, весьма вероятно, захотите, чтобы целиком вся транзакция была отозвана и начата заново. Транзакции очень существенны для систем, обновляющих несколько структур данных, например, баз данных. Такие обновления, даже основанные на одной операции, должны быть успешно завершены сразу для всех структур данных, именно для того, чтобы обеспечить успешное завершение одной этой операции.

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

Участие компонентов в транзакциях

Компонент может воспользоваться возможностями транзакций COM+, если он удовлетворяет следующим условиям. Во-первых, компонент должен быть внутрипроцессным сервером (то есть DLL). Во-вторых, он не должен быть свободно-поточным. Далее, если компонент создан в Visual С++, он должен реализовать фабрику классов (class factory) и использовать стандартную маршализацию. Кроме того, для компонента нужно будет создать библиотеку типов.

Если компонент удовлетворяет минимальным требованиям, чтобы получить поддержку транзакций, он должен быть зарегистрирован в COM+. В процессе регистрации тип транзакции, в которой участвует компонент, устанавливается в качестве свойства компонента. Например, на рис. 3 показано окно свойств компонента, для которого требуется транзакция, время ожидания завершения которой определено в 10 секунд.

Чтобы начать транзакцию на ASP-странице, поместите первой строкой страницы следующую директиву:

<%@ TRANSACTION = required %>

Для работы с транзакциями компонент должен ссылаться на экземпляр объекта ObjectContext (или интерфейса IObjectContext) или экземпляр интерфейса IContextState. Пометить компонент как готовый к принятию транзакции можно с помощью метода SetComplete объекта ObjectContext или метода SetMyTransactionVote интерфейса IContextState:

objContext.SetComplete

или:

objContext.SetMyTransactionVote adCommit

Пометить транзакцию для отзыва можно с помощью тех же интерфейсов:

objContext.SetAbort

или:

objContext.SetMyTransactionVote adAbort

Транзакции COM+ в действии показаны в примерах главы 9, посвященной созданию ASP-компонентов промежуточного слоя с помощью ADO. В этих примерах транзакции выполняются для обновления баз данных - и это их традиционное применение. Транзакции с базами данных можно выполнять непосредственно (не прибегая к транзакциям COM+) с помощью объекта ADO Connection. Тем не менее, примеры этой главы продемонстрируют, что гораздо удобней наладить взаимодействие компонентов и баз данных посредством транзакций COM+.

Транзакции COM+ можно также использовать для управления взаимодействием с другими ресурсами, например, с сообщениями в очереди сообщений. В главе 13, посвященной работе с компонентами MSMQ, транзакции управляют непрерывным удалением сообщений из очереди по мере получения к ним доступа.

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

Резервирование компонентов

Ранее уже отмечалось, что у интерфейса IObjectControl есть три метода: Activate, Deactivate и CanBePooled. У вас уже была возможность поработать с методами Activate и Deactivate, но для резервирования компонентов важен именно метод CanBePooled.

В случае резервирования объектов при пуске приложения COM+ создается минимальный резерв, или пул (pool), компонентов, и все запросы компонента обслуживаются из этого пула посредством менеджера пула (pool manager). Если менеджер получает запрос большего, чем имеется в пуле, числа экземпляров компонента, он создает другой экземпляр компонента, добавляя его в пул - до достижения максимального размера пула. Если же максимальный размер пула достигнут, запрос ставится в очередь до тех пор, пока компонент не станет доступным.

Компоненты, объединяемые в пул, должны соответствовать определенному набору условий. Во-первых, компонент не должен быть отдельно-поточным. Далее, компонент должен поддерживать агрегирование (aggregation), однако при этом свободно-поточный составитель (Free-Threaded Marshaler, FTM) использоваться не может.

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

Если компонент обращается к ресурсам, он должен реализовать три метода интерфейса IObjectControl - Activate, Deactivate и CanBePooled. Обратиться к ресурсу можно с помощью метода Activate (когда компонент создается на клиентской ASP-странице). Этот ресурс может быть высвобожден при высвобождении компонента клиентом (с помощью метода Deactivate). Кроме того, компонент обязан проверить, находятся ли его ресурсы в состоянии, когда их можно резервировать при деактивации компонента. Если резервирование возможно, метод компонента CanBePooled должен возвратить значение True, в противном случае, компонент должен возвратить значение False, чтобы предотвратить возврат компонента в пул.

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

Создать резервируемый компонент можно с помощью Visual C++ (или любого другого языка, поддерживающего свободно-поточную или произвольно-поточную модели). Для демонстрации резервирования объектов создайте с помощью мастера ATL COM AppWizard новый проект Visual С++ и назовите его asp0502. Оставьте установленные по умолчанию параметры для MTS, MFC, заместителя (proxy) и исполнителя (stub).

После генерации файлов проекта добавьте новый компонент с помощью мастера ATL Object Wizard. (Подробно работа с этим мастером рассмотрена в главе 14.) Выберите тип Simple Object (Простой объект). Назовите компонент pooledComponent, на вкладке Attributes (Атрибуты) выберите произвольно-поточную модель и поддержку агрегирования (но не поддержку FTM).

Для поддержки интерфейса IObjectControl добавьте в определения класса в файле pooledComponent.h следующую строку:

public IObjectControl,

Добавьте в данные COM ссылку на карту COM (COM map):

COM_INTERFACE_ENTRY(IObjectControl)

При работе с компонентом вам придется обращаться к интерфейсу IObjectContext и встроенному объекту ASP Response, поэтому добавьте в заголовочные файлы библиотеки типов службы COM+ и ASP следующее:

#include <comsvcs.h>
#include <asptlb.h>

Следует также добавить прототипы метода интерфейса IObjectControl и ссылку на два закрытых (private) члена данных типа интерфейсов IObjectContext и IResponse (встроенного объекта ASP Response). Полный программный код заголовочного файла для резервируемого компонента показан в листинге 5.3.

Листинг 3. Заголовочный файл резервируемого компонента

// pooledComponent.h : объявление CpooledComponent

#ifndef __POOLEDCOMPONENT_H_
#define __POOLEDCOMPONENT_H_

#include "resource.h" // основные символы
#include <comsvcs.h>
#include <asptlb.h>

/////////////////////////////////////////////////////////////////
// CpooledComponent
class ATL_NO_VTABLE CpooledComponent :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CpooledComponent, &CLSID_pooledComponent>,
public IObjectControl,
public IDispatchImpl<IpooledComponent, &IID_IpooledComponent,
                &LIBID_ASP0502Lib>
{
public:
CpooledComponent()
{
}

DECLARE_REGISTRY_RESOURCEID(IDR_POOLEDCOMPONENT)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CpooledComponent)
     COM_INTERFACE_ENTRY(IpooledComponent)
     COM_INTERFACE_ENTRY(IObjectControl)
     COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IpooledComponent
public:
     STDMETHOD(Activate)();
     STDMETHOD_(BOOL, CanBePooled)();
     STDMETHOD_(void, Deactivate)();

private:      CComPtr<IObjectContext> m_spObjectContext;
     CComPtr<IResponse> m_piResponse;
};

#endif //__POOLEDCOMPONENT_H_

Далее, с помощью вкладки Link (Связь) диалогового окна Project Settings (Настройки проекта) добавьте в список связанных библиотек проекта библиотеку служб COM+ (comsvcs.lib).

Вам придется реализовать три метода интерфейса IObjectControl. В CPP-файле компонента добавьте код, показанный в листинге 5.4. В этом коде экземпляры IObjectContext и IResponse создаются в методе Activate и высвобождаются в методе Deactivate. Кроме того, метод CanBePooled возвращает значение True и помечает, что компонент можно резервировать (помещать в пул).

Листинг 4. Реализация компонентом методов интерфейса IObjectControl

HRESULT CpooledComponent::Activate()
{
HRESULT hr;
CComBSTR bstrProp;
CComVariant vt;
CComPtr<IGetContextProperties> pProps; //Свойства контекста

IDispatch* piDispatch = NULL;

// получение ObjectContext
hr = CoGetObjectContext(IID_IObjectContext,
      (void **)&m_spObjectContext);

if (FAILED(hr)) return hr;

// получение ContextProperties
hr = m_spObjectContext
           ->QueryInterface( IID_IGetContextProperties,
           (void**)&pProps );
if (FAILED(hr)) return hr;

     // получение свойства Response
bstrProp = "Response";
hr = pProps->GetProperty( bstrProp, &vt ) ;
if (FAILED(hr)) return hr;

piDispatch = vt. pdispVal;
hr = piDispatch->QueryInterface( IID_IResponse,
           (void**)&m_piResponse );
return hr;
}

void CpooledComponent::Deactivate()
{
m_piResponse.Release();
m_spObjectContext.Release();
}

BOOL CpooledComponent::CanBePooled()
{
return TRUE;
}

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

С помощью вкладки ClassView (Просмотр классов) добавьте новому компоненту не принимающий никаких параметров метод testPooledComponent. Этот метод прост: он выдает с помощью объекта Response сообщение для web-страницы. Добавьте компоненту программный код метода, показанный в листинге 5.5.

Листинг 5. Единственный метод резервированного компонента

STDMETHODIMP CpooledComponent::testPooledComponent()
{
// печать сообщения
CComVariant vt("Привет от резервированного компонента"); m_piResponse->Write(vt);

return S_OK;
}

Чтобы воспользоваться резервированием компонентов, компонент нужно добавить в приложение COM+. Создайте новое приложение - с помощью консоли управления службами компонентов (Component Services Management Console) - или воспользуйтесь существующим приложением COM+ и добавьте компонент в приложение.

Добавив компонент в приложение COM+, откройте с помощью контекстного меню диалоговое окно Properties (Свойства) и перейдите на вкладку Activation (Активация). Установите флажок объединения компонентов, задайте минимальный размер пула 10, максимальный - 20.

При первом запуске приложение COM+ создает пул из 10 уже созданных компонентов. При обращении с ASP-страниц к этим компонентам они извлекаются из этого пула до тех пор, пока все не будут активированы. После этого все новые вызовы компонентов будут добавлять экземпляры этих компонентов в пул, пока не будет достигнут максимальный размер пула в 20 экземпляров.

Протестируйте компонент с помощью следующей тестовой ASP-страницы (asp0502.asp):

<%
Dim obj(20)

For i = 1 to 20
Set obj(i) = Server.CreateObject("asp0502.pooledComponent")
obj(i).testPooledComponent
Response.Write "<br>"
Next
%>

На этой странице создаются 20 экземпляров компонента и вызывается метод каждого из компонентов. Результатом обращения к этой ASP-странице будет список сообщений со строкой "Привет от резервированного компонента". Первые 10 экземпляров были созданы при запуске приложения COM+, а последние 10 - при обращении к ASP-странице.

Измените теперь число экземпляров на 21 и обратитесь к ASP-странице. Похоже, она виснет. Это происходит потому, что менеджер пула выдал все компоненты из доступного пула, вследствие чего достигнут максимальный размер пула. Запрос 21-го компонента ставится в очередь до тех пор, пока какой-нибудь компонент не освободится. Но поскольку до завершения страницы все компоненты остаются недоступными, а запрос компонента происходит на той же самой странице, экземпляр 21-го компонента не может быть создан, и страница зависает. Фактически страница будут продолжать висеть до истечения времени ожидания запроса компонента. После этого страница выведет следующее сообщение об ошибке ("активация COM+ не удалась, поскольку она не может быть завершена в течение заданного времени"):

COM+ activation failed because the activation could not be
completed in the specified amount of time.

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

Автор: Ш. Пауэрс.
Главы из книги "Службы COM+ в ASP-компонентах и ASP-приложениях", которую вы можете


последние новости
01.02.2013 15:18 | Интернет и малые предприятия...»
22.01.2013 13:30 | Провал с планшетом от Microsoft...»
27.11.2012 13:14 | Ключ к лучшему софту для вас!...»
22.11.2012 14:39 | Выбор домашнего компьютера...»
16.11.2012 15:17 | Старый знакомый - Dr. Web...»

Другие разделы
I2R Business
I2R Web Creation
I2R Computer
I2R-Журналы
I2R Business
I2R Web Creation
I2R Computer
рассылки библиотеки +
И2Р Программы
Всё о Windows
Программирование
Софт
Мир Linux
Галерея Попова
Каталог I2R
Партнеры
Amicus Studio
NunDesign
Горящие путевки, идеи путешествийMegaTIS.Ru

2000-2008 г.   
Все авторские права соблюдены.
Rambler's Top100